Limiting a many to many join
Hello,
I__m wondering if there is a way to limit a many to many join by a specific
value in a column in the join table. I have a join table that has the two
foreign key fields which are the ids to the tables and another column that
I want to limit on. So the SQL would be something like below but I want
to do it through ejb3. Any idea how this can be accomplished?
Select phone.number, __ from company, company_phone, phone where
company_phone.primay = __Y__ and company.id = company_phone.company_id and
phone.id = company_phone.phone_id and company.id = __1234__;
If so does it work for the other relationships (one to many and many to
one)?
Thanks,
Craig
Kodo does have support for limiting a join based on a constant value; we
call them "constant joins". See the following documentation, and let us
know if you have any questions:
http://solarmetric.com/Software/Documentation/4.0.0EA/docs/full/html/ref_guide_mapping_notes_nonstdjoins.html
Similar Messages
-
JOIN for many-to-many linked tables?
I have two tables, A and C, linked by a many-to-many intersection table B.
I'd like to do a select from A with a LEFT OUTER JOIN to C for items mapped via B. A row in A may or may not have rows in C linked to it.
I've tried to do a select using sub-selects but then I don't get the rows from A that don't have related rows in C.
When I try to use the syntax of a LEFT OUTER JOIN I can't figure out how to link A and C via the B table.
I would appreciate suggestions for how to approach this.
Thanks in advance,
GeorgeEXAMPLE
SQL> L
1 with A as (
2 select 1 col1, 1 col2 from dual union all
3 select 2 , 1 from dual union all
4 select 3 , 2 from dual)
5 ,
6 B as (
7 select 1 col2, 1 col3 from dual union all
8 select 2 , 3 from dual)
9 ,
10 C as (
11 select 1 col3 from dual union all
12 select 2 from dual union all
13 select 3 from dual
14 )
15 select *
16 from A
17 LEFT JOIN B ON (A.COL2=B.COL2)
18* LEFT JOIN C ON (B.COL3=C.COL3)
SQL> /
COL1 COL2 COL2 COL3 COL3
1 1 1 1 1
2 1 1 1 1
3 2 2 3 3 -
How many types of joins are there?
how many types of joins are there?
Edited by: Alvaro Tejada Galindo on Feb 21, 2008 4:58 PMHi,
Joins are used to fetch data fast from Database tables:
Tables are joined with the proper key fields to fetch the data properly.
If there are no proper key fields between tables don't use Joins;
Important thing is that don't USE JOINS FOR CLUSTER tableslike BSEG and KONV.
Only use for Transparenmt tables.
You can also use joins for the database VIews to fetch the data.
JOINS
... FROM tabref1 INNER JOIN tabref2 ON cond
The data is to be selected from transparent database tables and/or views determined by tabref1 and tabref2. tabref1 and tabref2 each have the same form as in variant 1 or are themselves Join expressions. The keyword INNER does not have to be specified. The database tables or views determined by tabref1 and tabref2 must be recognized by the ABAP Dictionary.
In a relational data structure, it is quite normal for data that belongs together to be split up across several tables to help the process of standardization (see relational databases). To regroup this information into a database query, you can link tables using the join command. This formulates conditions for the columns in the tables involved. The inner join contains all combinations of lines from the database table determined by tabref1 with lines from the table determined by tabref2, whose values together meet the logical condition (join condition) specified using ON>cond.
Inner join between table 1 and table 2, where column D in both tables in the join condition is set the same:
Table 1 Table 2
A B C D D E F G H
a1 b1 c1 1 1 e1 f1 g1 h1
a2 b2 c2 1 3 e2 f2 g2 h2
a3 b3 c3 2 4 e3 f3 g3 h3
a4 b4 c4 3 -
Inner Join
A B C D D E F G H
a1 b1 c1 1 1 e1 f1 g1 h1
a2 b2 c2 1 1 e1 f1 g1 h1
a4 b4 c4 3 3 e2 f2 g2 h2
Example
Output a list of all flights from Frankfurt to New York between September 10th and 20th, 2001 that are not sold out:
DATA: DATE LIKE SFLIGHT-FLDATE,
CARRID LIKE SFLIGHT-CARRID,
CONNID LIKE SFLIGHT-CONNID.
SELECT FCARRID FCONNID F~FLDATE
INTO (CARRID, CONNID, DATE)
FROM SFLIGHT AS F INNER JOIN SPFLI AS P
ON FCARRID = PCARRID AND
FCONNID = PCONNID
WHERE P~CITYFROM = 'FRANKFURT'
AND P~CITYTO = 'NEW YORK'
AND F~FLDATE BETWEEN '20010910' AND '20010920'
AND FSEATSOCC < FSEATSMAX.
WRITE: / DATE, CARRID, CONNID.
ENDSELECT.
If there are columns with the same name in both tables, you must distinguish between them by prefixing the field descriptor with the table name or a table alias.
In order to determine the result of a SELECT command where the FROM clause contains a join, the database system first creates a temporary table containing the lines that meet the ON condition. The WHERE condition is then applied to the temporary table. It does not matter in an inner join whether the condition is in the ON or WHEREclause. The following example returns the same solution as the previous one.
Example
Output of a list of all flights from Frankfurt to New York between September 10th and 20th, 2001 that are not sold out:
DATA: DATE LIKE SFLIGHT-FLDATE,
CARRID LIKE SFLIGHT-CARRID,
CONNID LIKE SFLIGHT-CONNID.
SELECT FCARRID FCONNID F~FLDATE
INTO (CARRID, CONNID, DATE)
FROM SFLIGHT AS F INNER JOIN SPFLI AS P
ON FCARRID = PCARRID
WHERE FCONNID = PCONNID
AND P~CITYFROM = 'FRANKFURT'
AND P~CITYTO = 'NEW YORK'
AND F~FLDATE BETWEEN '20010910' AND '20010920'
AND FSEATSOCC < FSEATSMAX.
WRITE: / DATE, CARRID, CONNID.
ENDSELECT.
Since not all of the database systems supported by SAP use the standard syntax for ON conditions, the syntax has been restricted. It only allows those joins that produce the same results on all of the supported database systems:
Only a table or view may appear to the right of the JOIN operator, not another join expression.
Only AND is possible in the ON condition as a logical operator.
Each comparison in the ON condition must contain a field from the right-hand table.
If an outer join occurs in the FROM clause, all the ON conditions must contain at least one "real" JOIN condition (a condition that contains a field from tabref1 amd a field from tabref2.
In some cases, '*' may be specified in the SELECT clause, and an internal table or work area is entered into the INTO clause (instead of a list of fields). If so, the fields are written to the target area from left to right in the order in which the tables appear in the FROM clause, according to the structure of each table work area. There can then be gaps between table work areas if you use an Alignment Request. For this reason, you should define the target work area with reference to the types of the database tables, not simply by counting the total number of fields. For an example, see below:
Variant 3
... FROM tabref1 LEFT OUTER JOIN tabref2 ON cond
Effect
Selects the data from the transparent database tables and/or views specified in tabref1 and tabref2. tabref1 und tabref2 both have either the same form as in variant 1 or are themselves join expressions. The keyword OUTER can be omitted. The database tables or views specified in tabref1 and tabref2 must be recognized by the ABAP-Dictionary.
In order to determine the result of a SELECT command where the FROM clause contains a left outer join, the database system creates a temporary table containing the lines that meet the ON condition. The remaining fields from the left-hand table (tabref1) are then added to this table, and their corresponding fields from the right-hand table are filled with ZERO values. The system then applies the WHERE condition to the table.
Left outer join between table 1 and table 2 where column D in both tables set the join condition:
Table 1 Table 2
A B C D D E F G H
a1 b1 c1 1 1 e1 f1 g1 h1
a2 b2 c2 1 3 e2 f2 g2 h2
a3 b3 c3 2 4 e3 f3 g3 h3
a4 b4 c4 3 -
Left Outer Join
A B C D D E F G H
a1 b1 c1 1 1 e1 f1 g1 h1
a2 b2 c2 1 1 e1 f1 g1 h1
a3 b3 c3 2 NULL NULL NULL NULL NULL
a4 b4 c4 3 3 e2 f2 g2 h2
Example
Output a list of all custimers with their bookings for October 15th, 2001:
DATA: CUSTOMER TYPE SCUSTOM,
BOOKING TYPE SBOOK.
SELECT SCUSTOMNAME SCUSTOMPOSTCODE SCUSTOM~CITY
SBOOKFLDATE SBOOKCARRID SBOOKCONNID SBOOKBOOKID
INTO (CUSTOMER-NAME, CUSTOMER-POSTCODE, CUSTOMER-CITY,
BOOKING-FLDATE, BOOKING-CARRID, BOOKING-CONNID,
BOOKING-BOOKID)
FROM SCUSTOM LEFT OUTER JOIN SBOOK
ON SCUSTOMID = SBOOKCUSTOMID AND
SBOOK~FLDATE = '20011015'
ORDER BY SCUSTOMNAME SBOOKFLDATE.
WRITE: / CUSTOMER-NAME, CUSTOMER-POSTCODE, CUSTOMER-CITY,
BOOKING-FLDATE, BOOKING-CARRID, BOOKING-CONNID,
BOOKING-BOOKID.
ENDSELECT.
If there are columns with the same name in both tables, you must distinguish between them by prefixing the field descriptor with the table name or using an alias.
Note
For the resulting set of a SELECT command with a left outer join in the FROM clause, it is generally of crucial importance whether a logical condition is in the ON or WHERE condition. Since not all of the database systems supported by SAP themselves support the standard syntax and semantics of the left outer join, the syntax has been restricted to those cases that return the same solution in all database systems:
Only a table or view may come after the JOIN operator, not another join statement.
The only logical operator allowed in the ON condition is AND.
Each comparison in the ON condition must contain a field from the right-hand table.
Comparisons in the WHERE condition must not contain a field from the right-hand table.
The ON condition must contain at least one "real" JOIN condition (a condition in which a field from tabref1 as well as from tabref2 occurs).
Note
In some cases, '*' may be specivied as the field list in the SELECT clause, and an internal table or work area is entered in the INTO clause (instead of a list of fields). If so, the fields are written to the target area from left to right in the order in which the tables appear in the llen in der FROM clause, according to the structure of each table work area. There can be gaps between the table work areas if you use an Alignment Request. For this reason, you should define the target work area with reference to the types of the database tables, as in the following example (not simply by counting the total number of fields).
Example
Example of a JOIN with more than two tables: Select all flights from Frankfurt to New York between September 10th and 20th, 2001 where there are available places, and display the name of the airline.
DATA: BEGIN OF WA,
FLIGHT TYPE SFLIGHT,
PFLI TYPE SPFLI,
CARR TYPE SCARR,
END OF WA.
SELECT * INTO WA
FROM ( SFLIGHT AS F INNER JOIN SPFLI AS P
ON FCARRID = PCARRID AND
FCONNID = PCONNID )
INNER JOIN SCARR AS C
ON FCARRID = CCARRID
WHERE P~CITYFROM = 'FRANKFURT'
AND P~CITYTO = 'NEW YORK'
AND F~FLDATE BETWEEN '20010910' AND '20010920'
AND FSEATSOCC < FSEATSMAX.
WRITE: / WA-CARR-CARRNAME, WA-FLIGHT-FLDATE, WA-FLIGHT-CARRID,
WA-FLIGHT-CONNID.
ENDSELECT. -
Many to many join table with different column names
Hi have a joint table with different column names as foreign keys in the joining
tables...
e.g. i have a many to many reltnshp btwn Table A and Table B ..and join table
C
both have a column called pk.
and the join table C has columns call fk1 and fk2
does cmd require the same column name in the join table as in the joining table?
are there any workarounds?
thanksHI,
No, the foreign key column names in the join table do not have to match the primary
key names in the joined tables.
-thorick -
How to resolve many-to-many join by 2 one-to-many joins
Hi,
I was asked many times how to resolve many to many relationship between two tables. I read to use 2 one -to- many relationships to resolve this. Can some expalin me when many to many relationship occurs between two tables and how to reslove them with practicle examples. Is there any article on this?
Regards,
Nanda KishoreHi,
Please check below link.
http://www.forumtopics.com/busobj/viewtopic.php?p=859029&sid=20d79e3df07b0d8b41aadfbd902bb6b2
http://blog.oaktonsoftware.com/2011/04/bridge-tables-and-many-to-many.html
Thanks,
Amit -
Hello,
Please help me create the many-to-many relationship between these tables that I willl need to do a Master Detail form. The master is tblStandardSheets (PK: ID) the detail is tblSubject (PK: SUBJECTID) and the link is tblLink (PK: RECID, FK: ID, SUBJECTID).
CREATE TABLE "tblStandardSheets"
( "ID" NUMBER NOT NULL ENABLE,
"SHEET" VARCHAR2(100),
"TITLE" VARCHAR2(255),
CONSTRAINT "tblStandardSheets_PK" PRIMARY KEY ("ID") ENABLE
CREATE OR REPLACE TRIGGER "BI_tblStandardSheets"
before insert on "tblStandardSheets"
for each row
begin
if :NEW."ID" is null then
select "TBLSTANDARDSHEETS_SEQ".nextval into :NEW."ID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblStandardSheets" ENABLE
CREATE TABLE "tblLink"
( "ID" NUMBER NOT NULL ENABLE,
"RECID" NUMBER NOT NULL ENABLE,
"SUBJECTID" NUMBER NOT NULL ENABLE,
CONSTRAINT "tblLink_PK" PRIMARY KEY ("RECID") ENABLE
ALTER TABLE "tblLink" ADD CONSTRAINT "TBLLINK_FK" FOREIGN KEY ("ID")
REFERENCES "tblStandardSheets" ("ID") ON DELETE CASCADE ENABLE
ALTER TABLE "tblLink" ADD CONSTRAINT "TBLLINK_FK2" FOREIGN KEY ("SUBJECTID")
REFERENCES "tblSubject" ("SUBJECTID") ON DELETE CASCADE ENABLE
CREATE OR REPLACE TRIGGER "BI_tblLink"
before insert on "tblLink"
for each row
begin
if :NEW."RECID" is null then
select "TBLLINK_SEQ".nextval into :NEW."RECID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblLink" ENABLE
CREATE TABLE "tblSubject"
( "SUBJECTID" NUMBER NOT NULL ENABLE,
"SUBJECT" VARCHAR2(255),
CONSTRAINT "tblSubject_PK" PRIMARY KEY ("SUBJECTID") ENABLE
CREATE OR REPLACE TRIGGER "BI_tblSubject"
before insert on "tblSubject"
for each row
begin
if :NEW."SUBJECTID" is null then
select "TBLSUBJECT_SEQ".nextval into :NEW."SUBJECTID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblSubject" ENABLE
ALTER TABLE "tblSubject" ADD CONSTRAINT "tblSubject_FK" FOREIGN KEY ("SUBJECTID")
REFERENCES "tblLink" ("SUBJECTID") ON DELETE CASCADE ENABLE
ORA-02270: no matching unique or primary key for this column-list
Edited by: user6753348 on Mar 31, 2009 1:39 PMLike this:
CREATE TABLE "tblStandardSheets"
( "ID" NUMBER NOT NULL ENABLE,
"SHEET" VARCHAR2(100 BYTE),
"TITLE" VARCHAR2(255 BYTE),
CONSTRAINT "tblStandardSheets_PK" PRIMARY KEY ("ID")
CREATE OR REPLACE TRIGGER "BI_tblStandardSheets"
before insert on "tblStandardSheets"
for each row
begin
if :NEW."ID" is null then
select "TBLSTANDARDSHEETS_SEQ".nextval into :NEW."ID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblStandardSheets" ENABLE
CREATE TABLE "tblSubject"
( "SUBJECTID" NUMBER NOT NULL ENABLE,
"SUBJECT" VARCHAR2(255 BYTE),
CONSTRAINT "tblSubject_PK" PRIMARY KEY ("SUBJECTID")
CREATE OR REPLACE TRIGGER "BI_tblSubject"
before insert on "tblSubject"
for each row
begin
if :NEW."SUBJECTID" is null then
select "TBLSUBJECT_SEQ".nextval into :NEW."SUBJECTID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblSubject" ENABLE
CREATE TABLE "HR"."tblLink"
( "ID" NUMBER NOT NULL ENABLE,
"RECID" NUMBER NOT NULL ENABLE,
"SUBJECTID" NUMBER NOT NULL ENABLE,
CONSTRAINT "tblLink_PK" PRIMARY KEY ("RECID")
CONSTRAINT "TBLLINK_FK" FOREIGN KEY ("ID")
REFERENCES "tblStandardSheets" ("ID") ON DELETE CASCADE ENABLE,
CONSTRAINT "TBLLINK_FK2" FOREIGN KEY ("SUBJECTID")
REFERENCES "tblSubject" ("SUBJECTID") ON DELETE CASCADE ENABLE
CREATE OR REPLACE TRIGGER "BI_tblLink"
before insert on "tblLink"
for each row
begin
if :NEW."RECID" is null then
select "TBLLINK_SEQ".nextval into :NEW."RECID" from dual;
end if;
end;
ALTER TRIGGER "BI_tblLink" ENABLE
/You have to create the sequences yourself...
HTH
Roel -
Insert/delete many to many join in 9.0.3
Can anyone tell me a good way to create/delete an intersection row in a many to many relationship? I can do it programmatically in the client, but I'd rather have the middle tier view object or application module handle the code. Currently I'm creating a JClient application but later I will be putting the application in a browser. I don't want to rewrite the code every time I change my client application.
ThanksI forgot to mention that I'm using the BC4J framework.
Mike -
I'm trying to create a denormalized view of my data that uses a typical join table to accomplish a many-to-many structure. The three tables involved are:
CREATE TABLE "POC_SUBNETS"
( "ID" NUMBER,
"OCTET1" NUMBER,
"OCTET2" NUMBER,
"OCTET3" NUMBER,
"OCTET4" NUMBER,
"SLASH" VARCHAR2(30),
"MASK" VARCHAR2(30),
"DESCRIPTION" VARCHAR2(255),
"ASSIGNED" VARCHAR2(3),
CONSTRAINT "POC_SUBNETS_PK" PRIMARY KEY ("ID") ENABLE,
CONSTRAINT "POC_SN_ASSGN_CON" CHECK ( "ASSIGNED" in ('YES', 'NO')) ENABLE
CREATE TABLE "POC_CONTACTS"
( "UNID" VARCHAR2(30),
"FNAME" VARCHAR2(30),
"LNAME" VARCHAR2(30),
"DESK_PHONE" VARCHAR2(30),
"CELL_PHONE" VARCHAR2(30),
"PAGER" VARCHAR2(30),
"OTHER_PHONE" VARCHAR2(30),
"EMAIL" VARCHAR2(50),
"ORG_ID" VARCHAR2(10),
CONSTRAINT "POC_CONTACTS_PK" PRIMARY KEY ("UNID") ENABLE,
CONSTRAINT "POC_CONTACTS_CON" UNIQUE ("FNAME", "LNAME") ENABLE
CREATE TABLE "POC_SUBNET_CONTACTS"
( "SUBNET_ID" NUMBER,
"UNID" VARCHAR2(30),
"CTYPE" VARCHAR2(30),
CONSTRAINT "POC_SUBNET_CONTACTS_PK" PRIMARY KEY ("SUBNET_ID", "UNID", "CTYPE") ENABLE
)Obviously, this structure will allow many contacts to have many subnets but each entry in poc_subnet_contacts must be a unique combination of subnet_id, unid, and ctype.
Well, now that we've satisfied our requirement to allow this arrangement the users want to see a denormalized view of the data whereby the subnets show each of the zero to n contacts on the same row as the subnet. Something like this:
subnet_id, unid1, unid2, unid3, unidn, etc...
In truth, I can limit the number of contacts shown per subnet to 3, but I'm curious what the best way of accomplishing this denormalized view is. Here's something that I came up with:
select id, octet1, octet2, octet3, octet4,
(select unid from poc_subnet_contacts where id = subnet_id and ctype = 'LAN') LAN_UNID,
(select unid from poc_subnet_contacts where id = subnet_id and ctype = 'SEC') SEC_UNID,
(select unid from poc_subnet_contacts where id = subnet_id and ctype = 'NSC') NSC_UNID,
(select unid from poc_subnet_contacts where id = subnet_id and ctype = 'FAC') FAC_UNID
from poc_subnetsThis has the obvious limitation that the contact has to be of a specific type to appear and those may not always exist.
There also could be multiple contacts of the same type that I would like to show, if possible. This situation has caused the dreaded ORA-01427: single-row subquery returns more than one row error.
Would a materialized view help in this situation?
Earlbiswabijay,
Thanks for the reply. What you've suggested works similarly to my original - presumably without the problem of returning multiple rows for a single row query because of the use of MAX. That's a step in the right direction. Thank you for that.
What about the idea of being able to more dynamically add columns and the case where I might want to show multiple contacts of the same type on one row? Any ideas?
In Excel and Access this is called a crosstab query. Is there anything similar in Oracle?
Earl
P.S. I apologize in advance for mentioning the 'E' and 'A' words here on the Oracle forums. And no, I don't want to use 'E' OR 'A'. Thank you. -
Many-to-many performance issue
I realize that many-to-many joins have been discussed before (yes, I looked through many threads), but I'm having a slight variation on the issue. Our data warehouse has been functioning for a couple of years now, but we're now experiencing a dramatic degradation in report performance. I'll tell you everything I know and what I've tried. My hope is that someone will have an idea that hasn't occurred to me yet.
The troubling data links deal with accounts and account_types. Each transaction will have one account, but each account can have multiple account_types and each account_type is made up of multiple accounts. It ends up looking like this:
Transaction_cube --< account_dimension >--< account_type_table
Given the many-to-many relationship between account and account_type, this is the only architecture I could come up with that will maintain data integrity in the transaction cube.
I know that this is the cause of the performance issues because the reports run normally when this is removed. The volume of data obviously increases over time, but the problem appeared very suddenly -- not a gradual degradation that one would expect from a volume issue. The cube is partitioned by year and we're a little below last year's growth.
The other fact to throw in is that the account_type table did increase in size by an additional 30% when we first noticed the problem. However, the business was able to go back and remove half of the account_types (unused types) so now the table has fewer rows than it had before we noticed the problem (~15k rows in the account_type table).
We have tried pinning the table so that it remain in memory, but that did not help. I tried creating a materialized view combining accounts and account_types with a similar lack of improvement. I've tried adding indexes, but there is still a full-table scan. All database objects are analyzed nightly after the data load is completed.
I'm fresh out of ideas at this point. Any suggestions and/or ideas would be greatly appreciated.I've thought about that. What it would mean would be aprox. 20 additional columns for each of the different account_types. Unfortunately, that would also mean that all the reports that use the account_type would have to have a condition:
WHERE acct_type1='Income Stmt." OR acct_type2='Income Stmt." OR ....
Since the account_types are not set up in a hierarchy and there must be only one row for account, I'm not sure that this is a feasible solution.
Thank you for the suggestion. -
Creating data in a many-to-many-relationship
Hello,
we really have problems in implementing a JClient dialog based on BC4J for creating data in a many to many relationship - especially with cascade delete on both sides.
Simplified our tables look like:
create table A_TABLE
A_ID VARCHAR2(5) not null,
A_NAME VARCHAR2(30) not null,
constraint PK_A_TABLE primary key (A_ID),
constraint UK_A_TABLE unique (A_NAME)
create table B_TABLE
B_ID VARCHAR2(5) not null,
B_NAME VARCHAR2(30) not null,
constraint PK_B_TABLE primary key (B_ID),
constraint UK_B_TABLE unique (B_NAME)
create table AB_TABLE
A_ID VARCHAR2(5) not null,
B_ID VARCHAR2(5) not null,
constraint PK_AB_TABLE primary key (A_ID, B_ID),
constraint FK_AB_A foreign key (A_ID) references A_TABLE (A_ID) on delete cascade,
constraint FK_AB_B foreign key (B_ID) references B_TABLE (B_ID) on delete cascade
Could JDev Team please provide a BC4J/JClient sample that performs the following task:
The dialog should use A_TABLE as master and AB_TABLE as detail. The detail displays the names associated with the IDs. Next to AB_TABLE should be a view of B_TABLE which only displays rows that are currently not in AB_TABLE. Two buttons are used for adding and removing rows in AB_TABLE. After adding or removing rows in the intersection the B_TABLE view should be updated. The whole thing should work in the middle and client tier. This means no database round trips after each add/remove, no posts for AB_TABLE and no query reexecution for B_TABLE until commit/rollback.
This is a very common szenario: For an item group (A_TABLE) one can select and deselect items (AB_TABLE) from a list of available items (B_TABLE). Most of JDeveloper4s wizards use this. They can handle multi/single selections, selections from complex structures like trees and so on. Ok, the wizards are not based on BC4J - or? How can we do it with BC4J?
Our main problems are:
1. Updating the view of B_TABLE after add/remove reflecting the current selection
2. A good strategy for displaying the names instead of the IDs (subqueries or joining the three tables)
3. A JBO-27101 DeadEntityAccessException when removing an existing row from AB_TABLE and adding it again
Other problems:
4. We get a JBO-25030 InvalidOwnerException when creating a row in AB_TABLE. This is caused by the composition. We workaround this using createAndInitRow(AttributeList) on the view object (instead of create()). This is our add-Action:
ViewObject abVO = panelBinding.getApplicationModule().findViewObject("ABView");
ViewObject bVO = panelBinding.getApplicationModule().findViewObject("BView");
Row bRow = bVO.getCurrentRow();
NameValuePairs attribList = new NameValuePairs(
new String[]{"BId"}, new Object[]{bRow.getAttribute("BId")});
Row newRow = abVO.createAndInitRow(attribList);
abVO.insertRow(newRow);
5. After inserting the new row the NavigationBar has enabled commit/rollback buttons and AB_TABLE displays the row. But performing a commit does nothing. With the following statement after insertRow(newRow) the new row is created in the database:
newRow.setAttribute("BId", bRow.getAttribute("BId"));
Please give us some help on this subject.
Best regards
Michael Thal<Another attempt to post a reply. >
Could JDev Team please provide a BC4J/JClient sample
that performs the following task:
The dialog should use A_TABLE as master and AB_TABLE
as detail. The detail displays the names associated
with the IDs. Next to AB_TABLE should be a view of
B_TABLE which only displays rows that are currently
not in AB_TABLE. Two buttons are used for adding and
removing rows in AB_TABLE. After adding or removing
rows in the intersection the B_TABLE view should be
updated. The whole thing should work in the middle
and client tier. This means no database round trips
after each add/remove, no posts for AB_TABLE and no
query reexecution for B_TABLE until commit/rollback.
This is a very common szenario: For an item group
(A_TABLE) one can select and deselect items
(AB_TABLE) from a list of available items (B_TABLE).
Most of JDeveloper4s wizards use this. They can
handle multi/single selections, selections from
complex structures like trees and so on. Ok, the
wizards are not based on BC4J - or? How can we do it
with BC4J?
Our main problems are:
1. Updating the view of B_TABLE after add/remove
reflecting the current selectionYou should be able to use insertRow() to insert the row into proper collection.
However to remove a row only from the collection, you need to add a method on the VO subclasses (and perhaps export this method so that the client side should see it) to unlink a row from a collection (but not remove the associated entities from the cache).
This new method should use ViewRowSetImpl.removeRowAt() method to remove the row entry at the given index from it's collection. Note that this is an absolute index and not a range index in the collection.
2. A good strategy for displaying the names instead
of the IDs (subqueries or joining the three tables)You should join the three tables by using reference (and perhaps readonly) entities.
3. A JBO-27101 DeadEntityAccessException when
removing an existing row from AB_TABLE and adding it
againThis is happening due to remove() method on the Row which is marking the row as removed. Attempts to add this row into another collection will throw a DeadEntityAccessException.
You may 'remove the row from it's collection, then call 'Row.refresh' on it to revert the entity back to undeleted state.
>
Other problems:
4. We get a JBO-25030 InvalidOwnerException when
creating a row in AB_TABLE. This is caused by the
composition. We workaround this using
createAndInitRow(AttributeList) on the view object
(instead of create()). This is our add-Action:
ViewObject abVO =
O =
panelBinding.getApplicationModule().findViewObject("AB
iew");
ViewObject bVO =
O =
panelBinding.getApplicationModule().findViewObject("BV
ew");
Row bRow = bVO.getCurrentRow();
NameValuePairs attribList = new NameValuePairs(
new String[]{"BId"}, new
String[]{"BId"}, new
Object[]{bRow.getAttribute("BId")});
Row newRow = abVO.createAndInitRow(attribList);
abVO.insertRow(newRow);This is a handy approach. Note that Bc4j framework does not support dual composition where the same detail can be owned by two or more masters. In those cases, you also need to implement post ordering to post the masters before the detail (and reverse ordering for deletes).
>
5. After inserting the new row the NavigationBar has
enabled commit/rollback buttons and AB_TABLE displays
the row. But performing a commit does nothing. With
the following statement after insertRow(newRow) the
new row is created in the database:
newRow.setAttribute("BId",
d", bRow.getAttribute("BId"));This bug in JDev 903 was fixed and a patch set (9.0.3.1) is (I believe) available now via MetaLink.
>
>
Please give us some help on this subject.
Best regards
Michael Thal -
Many-to-many Performance Problem (Using FAQ Template)
Having read "HOW TO: Post a SQL statement tuning request - template posting" I have gathered:
I have included some background information at the bottom of the post
The following SQL statement has been identified as performing poorly. It takes ~160 seconds to execute, but similar (shown below first statement) SQL statements executes in ~1 second.
SQL taking 160 seconds:
SELECT
a.*
FROM
table_a a
INNER JOIN table_a_b ab ON a.id = ab.media_fk
WHERE
ab.channel_fk IN (7, 1);SQL taking ~1 second or less
ab.channel_fk IN (7);Or even:
ab.channel_fk IN (6, 9, 170, 89);The purpose of the SQL is to return rows from table_a that are associated with table_b (not in SQL) through the junction table table_a_b.
The version of the database is 10.2.0.4.0
These are the parameters relevant to the optimizer:
show parameter optimizer;
NAME TYPE VALUE
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.2.0.4
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string ALL_ROWS
optimizer_secure_view_merging boolean TRUE
show parameter db_file_multi;
NAME TYPE VALUE
db_file_multiblock_read_count integer 16
show parameter db_block_size;
NAME TYPE VALUE
db_file_multiblock_read_count integer 16
select sname, pname, pval1, pval2 from sys.aux_stats$;
SNAME PNAME PVAL1 PVAL2
SYSSTATS_INFO STATUS COMPLETED
SYSSTATS_INFO DSTART 07-18-2006 23:19
SYSSTATS_INFO DSTOP 07-25-2006 23:19
SYSSTATS_INFO FLAGS 0
SYSSTATS_MAIN SREADTIM 5.918
SYSSTATS_MAIN MREADTIM 7.889
SYSSTATS_MAIN CPUSPEED 1383
SYSSTATS_MAIN MBRC 8
SYSSTATS_MAIN MAXTHR 1457152
SYSSTATS_MAIN SLAVETHR -1Here is the output of EXPLAIN PLAN:
PLAN_TABLE_OUTPUT
Plan hash value: 3781163428
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1352K| 771M| | 60042 (3)| 00:05:56 |
|* 1 | HASH JOIN | | 1352K| 771M| 27M| 60042 (3)| 00:05:56 |
|* 2 | INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 | 1352K| 11M| | 1816 (4)| 00:00:11 |
| 3 | TABLE ACCESS FULL | TABLE_A | 2190K| 1230M| | 32357 (4)| 00:03:12 |
Predicate Information (identified by operation id):
1 - access(""AB"".""MEDIA_FK""=""A"".""ID"")
2 - filter(""AB"".""CHANNEL_FK""=1 OR ""AB"".""CHANNEL_FK""=7)
Note
- 'PLAN_TABLE' is old versionFor reference, the EXPLAIN PLAN when using
ab.channel_fk IN (6, 9, 170, 89);which executes in ~1 second is:
PLAN_TABLE_OUTPUT
Plan hash value: 794334170
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 143K| 81M| | 58982 (3)| 00:05:50 |
|* 1 | HASH JOIN | | 143K| 81M| 2952K| 58982 (3)| 00:05:50 |
| 2 | INLIST ITERATOR | | | | | | |
|* 3 | INDEX RANGE SCAN| C_M_INDEX | 143K| 1262K| | 1264 (1)| 00:00:08 |
| 4 | TABLE ACCESS FULL| TABLE_A | 2190K| 1230M| | 32357 (4)| 00:03:12 |
Predicate Information (identified by operation id):
1 - access(""AB"".""MEDIA_FK""=""A"".""ID"")
3 - access(""AB"".""CHANNEL_FK""=6 OR ""AB"".""CHANNEL_FK""=9 OR
""AB"".""CHANNEL_FK""=89 OR ""AB"".""CHANNEL_FK""=170)
Note
- 'PLAN_TABLE' is old versionHere is the output of SQL*Plus AUTOTRACE including the TIMING information:
SQL> set autotrace traceonly arraysize 100;
SQL> SELECT
2 a.*
3 FROM
4 table_a a
5 INNER JOIN table_a_b ab ON a.id = ab.media_fk
6 WHERE
7 ab.channel_fk IN (7, 1);
1336148 rows selected.
Execution Plan
Plan hash value: 3781163428
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1352K| 771M| | 60042 (3)| 00:05:56 |
|* 1 | HASH JOIN | | 1352K| 771M| 27M| 60042 (3)| 00:05:56 |
|* 2 | INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 | 1352K| 11M| | 1816 (4)| 00:00:11 |
| 3 | TABLE ACCESS FULL | TABLE_A | 2190K| 1230M| | 32357 (4)| 00:03:12 |
Predicate Information (identified by operation id):
1 - access("AB"."MEDIA_FK"="A"."ID")
2 - filter("AB"."CHANNEL_FK"=1 OR "AB"."CHANNEL_FK"=7)
Note
- 'PLAN_TABLE' is old version
Statistics
10586 recursive calls
0 db block gets
200457 consistent gets
408343 physical reads
0 redo size
498740848 bytes sent via SQL*Net to client
147371 bytes received via SQL*Net from client
13363 SQL*Net roundtrips to/from client
49 sorts (memory)
0 sorts (disk)
1336148 rows processedThe TKPROF output for this statement looks like the following:
TKPROF: Release 10.2.0.4.0 - Production on Mon Oct 1 12:23:21 2012
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Trace file: ..._ora_4896.trc
Sort options: default
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
ALTER SYSTEM SET TIMED_STATISTICS = TRUE
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.03 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
total 2 0.00 0.03 0 0 0 0
Misses in library cache during parse: 0
Parsing user id: 21
SELECT
a.*
FROM
table_a a
INNER JOIN table_a_b ab ON a.id = ab.media_fk
WHERE
ab.channel_fk IN (7, 1)
call count cpu elapsed disk query current rows
Parse 1 0.01 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 27.23 163.57 179906 198394 0 16
total 4 27.25 163.58 179906 198394 0 16
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 21
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 2 0.01 0.00 0 0 0 0
Execute 2 0.00 0.03 0 0 0 0
Fetch 2 27.23 163.57 179906 198394 0 16
total 6 27.25 163.62 179906 198394 0 16
Misses in library cache during parse: 1
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 0 0.00 0.00 0 0 0 0
Execute 0 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
total 0 0.00 0.00 0 0 0 0
Misses in library cache during parse: 0
2 user SQL statements in session.
0 internal SQL statements in session.
2 SQL statements in session.
Trace file: ..._ora_4896.trc
Trace file compatibility: 10.01.00
Sort options: default
1 session in tracefile.
2 user SQL statements in trace file.
0 internal SQL statements in trace file.
2 SQL statements in trace file.
2 unique SQL statements in trace file.
46 lines in trace file.
187 elapsed seconds in trace file.The DBMS_XPLAN.DISPLAY_CURSOR output:
select * from table(dbms_xplan.display_cursor('474frsqbc1n4d', null, 'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
SQL_ID 474frsqbc1n4d, child number 0
SELECT /*+ gather_plan_statistics */ c.* FROM table_a c INNER JOIN table_a_b ab ON c.id = ab.media_fk WHERE ab.channel_fk IN (7, 1)
Plan hash value: 3781163428
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem |
|* 1 | HASH JOIN | | 1 | 1352K| 1050 |00:00:40.93 | 198K| 182K| 209K| 29M| 5266K| 3320K (1)|
|* 2 | INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 | 1 | 1352K| 1336K|00:00:01.34 | 10874 | 0 | 0 | | | |
| 3 | TABLE ACCESS FULL | TABLE_A | 1 | 2190K| 2267K|00:02:45.56 | 187K| 182K| 0 | | | |
Predicate Information (identified by operation id):
1 - access(""AB"".""MEDIA_FK""=""C"".""ID"")
2 - filter((""AB"".""CHANNEL_FK""=1 OR ""AB"".""CHANNEL_FK""=7))Thank you for reading I'm looking forward for suggestions how to improve the performance of this statement.
h3. Backgroud
Many years ago my company made the decision to store many-to-many relationships in our database using pipe delimited fields. An example field value:
'|ABC|XYZ|VTR|DVD|'Each delimited value refers to a unique 'short code' in TABLE_B (There is also a true numeric foreign key in TABLE_B which is what I'm using in the junction table). We regularly search using these column with the following style SQL:
WHERE
INSTR(pipedcolumn, '|ABC|') > 0
OR INSTR(pipedcolumn, '|XYZ|' > 0
...Appropriate indexes have been created over the years to make this process as fast a possible.
We now have an opportunity to fix some of these design mistakes and implement junction tables to replace the piped field. Before this we decided to take a copy of a database from a customer with the largest record set and test. I created a new junction table:
TABLE_A_B DDL:
CREATE TABLE TABLE_A_B (
media_fk NUMBER,
channel_fk NUMBER,
PRIMARY KEY (media_fk, channel_fk),
FOREIGN KEY (media_fk) REFERENCES TABLE_A (ID),
FOREIGN KEY (channel_fk) REFERENCES TABLE_B (ID)
) ORGANIZATION INDEX COMPRESS;
CREATE INDEX C_M_INDEX ON TABLE_A_B (channel_fk, media_fk) COMPRESS;And parsing out a pipe delimited field, populated this new table.
I then compared the performance of the following SQL:
SELECT
a.*
FROM
table_a a
INNER JOIN table_a_b ab ON a.id = ab.media_fk
WHERE
ab.channel_fk IN (x, y, n); -- Can be Many Minutes
--vs.
SELECT
a.*
FROM
table_a a
WHERE
INSTR(OWNERS,'|x|') >0
OR INSTR(OWNERS,'|y|') >0
OR INSTR(OWNERS,'|n|') >0; -- About 1 second seemingly regardlessWhen x, y, n are values that occur less frequently in TABLE_A_B.CHANNEL_FK the performance is comparable. However once the frequency of x, y, n increases the performance suffers. Here is a summary of the CHANNEL_FK data in TABLE_A_B:
--SQL For Summary Data
SELECT channel_fk, count(channel_fk) FROM table_a_b GROUP BY channel_fk ORDER BY COUNT(channel_fk) DESC;
CHANNEL_FK COUNT(CHANNEL_FK)
7 780741
1 555407
2 422493
3 189493
169 144663
9 79457
6 53051
171 28401
170 19857
49 12603
...I've noticed that once I use any combination of values which occur more than about 800,000 times (i.e. IN (7, 1) = 780741 + 555407 = 1336148) then I get performance issues.
I'm finding it very difficult to accept that the old pipe delimited fields are a better solution (ignoring everything other than this search criteria!).
Thank you for reading this far. I truly look forward to suggestions on how to improve the performance of this statement.
Edited by: user1950227 on Oct 1, 2012 12:06 PM
Renamed link table in DDL.Possibly not, I followed the instructions as best as I could but may have missed things.
h5. 1. DDL for all tables and indexes?
h6. - TABLE_A_B is described above and has a total of 2,304,642 rows. TABLE_A and TABLE_B are described below.
h5. 2. row counts for all tables?
h6. - See below
h5. 3. row counts for the predicates involved?
h6. - Not sure what your asking for, I have a summary of data in TABLE_A_B above. Could you clarify please?
h5. 4. Method and command used to collect stats on the tables and indexes?
h6. - For the stats I collected above I have included the command used to collect the data. If you are asking for further data I am happy to provide it but need more information. Thanks.
TABLE_A has 2,267,980 rows. The DLL that follows has been abbriviated, only the column involved is described.
-- DDL for Table TABLE_A
CREATE TABLE "NS"."TABLE_A"
( "ID" NUMBER
--Lots more columns
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "CUSTOMNAMESPACE" ;
-- DDL for Index ID_PK
CREATE UNIQUE INDEX "NS"."MI_PK" ON "NS"."TABLE_A" ("ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 16384 NEXT 29458432 MINEXTENTS 1 MAXEXTENTS 505
PCTINCREASE 50 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "SYSTEM" ;
-- Constraints for Table TABLE_A
ALTER TABLE "NS"."TABLE_A" ADD CONSTRAINT "MI_PK" PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 16384 NEXT 29458432 MINEXTENTS 1 MAXEXTENTS 505
PCTINCREASE 50 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "SYSTEM" ENABLE;
ALTER TABLE "NS"."TABLE_A" MODIFY ("ID" NOT NULL ENABLE);TABLE_B has 22 rows. The DLL that follows has been abbriviated, only the column involved is described.
-- DDL for Table TABLE_B
CREATE TABLE "NS"."TABLE_B"
"ID" NUMBER
--Lots more columns
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "CUSTOMNAMESPACE" ;
-- DDL for Index CID_PK
CREATE UNIQUE INDEX "NS"."CID_PK" ON "NS"."TABLE_B" ("ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 16384 NEXT 16384 MINEXTENTS 1 MAXEXTENTS 505
PCTINCREASE 50 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "SYSTEM" ;
-- Constraints for Table TABLE_B
ALTER TABLE "NS"."TABLE_B" ADD CONSTRAINT "CID_PK" PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 16384 NEXT 16384 MINEXTENTS 1 MAXEXTENTS 505
PCTINCREASE 50 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "SYSTEM" ENABLE;
ALTER TABLE "NS"."TABLE_B" MODIFY ("ID" NOT NULL ENABLE);Edited by: davebcast on Oct 1, 2012 8:51 PM
Index name incorrect
Edited by: davebcast on Oct 1, 2012 8:52 PM -
Just asking for some help with some search terms, as I know that this topic has been argued out somewhere. I just haven't been able to find it:
If I'm setting up a cross-reference/junction table in order to fulfill a many-to-many requirement, should I create a technical key as a primary key with a unique index on the combined foreign keys? Or should I make the combination of the foreign keys the primary key?
Our newest standards force a technical key on all tables, and one of the Developers is asking why that's necessary on a cross-reference table. I've searched on "cross reference table primary key", "junction table primary key". Most answers suggesting a technical key are due to database performance issues that can be solved with it (not suggested for that reason for Oracle that I've found yet).
--=Chuck>
If I'm setting up a cross-reference/junction table in order to fulfill a many-to-many requirement, should I create a technical key as a primary key with a unique index on the combined foreign keys? Or should I make the combination of the foreign keys the primary key?
>
Assuming that each of your foreign keys is a surrogate key and not an actual data value, I have to agree with Dan on this one.
The two primary attributes that a key value should have are: 1) it should be unique and 2) it should have no inherent meaning.
By 'no inherent meaning' I mean it should NOT be a data value or have any meaning whatsoever attached to its value. If the value were to change it would have no impact at all on the actual data though naturally the value has to be changed the same everywhere it is used.
A classic example in the U.S. is social security number. It should NOT be used as a key even though it might be considered a 'natural' key.
The value is a data item that has meaning and is subject to change if for no other reason than typographical error. It is the problems involved in making changes to data items used as keys that surrogate keys are intended to prevent.
A surrogate key (even a sequence) has no inherent meaning. If a value of 2 is being used in a system and, unknown to you, someone changes the value to a 3 everywhere in your system that it is used you will never notice it.
I have seen no standard suggesting that multi-column surrogate keys are inappropriate. Your intersect table can use the combination of the foreign keys as the primary key and fulfill the contract of using surrogate keys.
Sven suggested this
>
For example you later discover that you want a detail table for your joined table. Then the detail table would need only one column as a foreign key constraint, instead of two (which can have major performance implications).
>
If if was desired to meet that future requirement by using one column you can easily do so by adding a new column specifically for that purpose without any impact whatsoeve on the existing system.
As for this possible architecture change
>
Or you add some third column to include into the uniqueness logic.
>
Well that requirement is a fundamental change to your existing one. The existing requirement is that the combination of the two foreign keys should be unique. It is not clear if Sven was suggesting that that requirement is no longer valid or if rather suggesting that there is no an ADDITIONAL requirement that those two values as well as a third should also be unique.
If you need to implement uniqueness for the two values you currently have as well as for those combined with a third value that would be better implemented by creating yet another INTERSECT table specifically for that purpose and leave the existing intersect table in place. That architecture approach expands the data model without disrupting the existing one.
The main design goal, in my opinion, should always be to produce a design which most easily meets current requirements without foreclosing the ability to meet unknown future requirements. -
Many-to-many relationship - show all values
Hi,
I'm building a cube in 2008R2 and have a many-to-many relationship through a bridging table but when displaying the results it is effectively an inner join and I would like to see a full outer join with the unknown rows set to "unknown".
I've managed to achieve this by doing a full outer join in the view that creates my bridging table and having an unknown member in my dimensions but then when I added in a dimension that wasn't directly related to the bridging table the unknown rows
were removed again. I was able to get past this by adding a row to my fact table with all the keys set to unknown and the metrics set to zero.
Whilst this works it really does not seem like an ideal solution, especially as previously empty metrics are now returning a zero.
Is there any way to achieve this in SSAS? Perhaps in the way unknown members are processed?
Thanks,cccparkhill,
What you did is the only way to achieve what you want.
In cubes you connect Dimensions throw Facts. By definition dimensions are
“How do business people describe the data that
results from the business process?”
and facts are “What are we measuring?”, noting the underlined
we can understand that _normally and usually_ the relation between the dimensions and the facts represent incidents happened in the real world ... the way you approach, think, and deal with dimensions and facts in cubes is different than dealing with tables
in normal relational transnational database.
Personally I do what you did when I want to achieve "Left join"
Please mark this reply as the answer
or vote as helpful, as appropriate, to make it useful for other readers -
Many to many relationships (Again)
Hello,
There was a posting on above subject.
Re: Many to many relationships between Fact and Dimension
They asked to look chapter 3 in the user's guide... <http://download.oracle.com/docs/pdf/B10996_01.pdf>. chapter 3 talks about defining Oracle Data Objects. I could find above subject in chapter 3 .
Here is our situation We are using OWB 9.2.0.2.8. We are in a situation to build ETL from denormalized (relational tables) source to normalized target (relational tables). It is not a data warehouse situation. It could be a reverse of data warehouse. As given below
Supplier >--------------------<Item
becomes Supplier ------<supp_item.>--------------Item after many to many resolution, Where supp_item is interface table.
We were able build Supplier and Item through seprate mapping. I could build supp_item through post mapping process. I look for alternate thought as well.
We are using separate sequence number for Supplier , Item and supp_item. The sequences will be surrogate keys such as Supplier ( Suppseq(PK)), Item (Itemseq (PK)) and supp_item(suppitemseq (PK)) Here is the sample
Supplier
001|S001
002|S002
003|S003
004|S004
Item
001|I001
002|I002
003|I003
Supp_item (Suppseq|ItemSeq)
001|002 --- S001 I002
001003 -----S001 I003
001|004 ----- S001 I 004
002|002 ---- S 002 I002
002|003 ---- S 002 I003
003|001 --- S 003 I 003
003|003 --- S 003 I 003
Did any body face such situation? What is the best way to create a mapping (single map or multiple map with processflow sequence) for this situation?
Let me know the steps exercised in OWB for this situation.
I appreciate your help.
Regards
RamHi Ram,
The easiest way to do this, would be to:
- Load supplier in one mapping and generate the surrogate key.
- Load item another (or the same) mapping and generate the surrogate key.
- Load supplier_item in its own separate mapping, using a key lookup (or join) to (with) the supplier and item tables.
Needless to say, you should create unique keys on the natural key of the supplier and item tables, to enable quick index-based lookups and make sure you get one unique value for every value of the natural key.
Hope this helps,
Mark. -
Working with many-to-many relationships
I am about to start my first experience with many-to-many
relationships using PHP and MySQL.
My project is to create an events registration form. As you
know, there can be many events and many participants attending many
events.
I am not sure on how to structure my database and tables so I
will first show you what I have:
create table programs (
program_id int not null primary key auto_increment,
program_name varchar(100) not null,
program_date varchar(25) not null,
program_time varchar(25) not null,
program_coordinator varchar(100),
program_seats int not null
create table participants (
participant_id int not null primary key auto_increment,
participant_name varchar(100) not null,
participant_phone varchar(12) not null
I know that I need a middle table to join the two.
create table programs_participants (
program_id int references program(id),
participants_id int references participants(id),
primary key (program_id, participants_id)
My problem is, how do I submit to both the participants AND
the programs_participants table together? Or is this not possible?
The participants are not already in the database when we register
them. We enter their personal info and select their desired events
from checkboxes on the same page.
Thanks for your help.> My problem is, how do I submit to both the participants
AND the
> programs_participants table together? Or is this not
possible? The
> participants are not already in the database when we
register them. We
> enter
> their personal info and select their desired events from
checkboxes on the
> same
> page.
What you need to do is a multi-step insert.
First, you insert the new participant into the participant
table, then use
the @@identity command to get the uniqueID of that newly
entered record.
Then you can take that uniqueID to build the entry for the
programs_participants table.
If you use a stored procedure, you should be able to do all
of that with
only having to create one call to the DB from your
Application.
_Darrel
Maybe you are looking for
-
Installation problems with Photoshop elements on my Mac
I try to installate PhE en Pr E; I get a message close ElementsAutoanalyser. Close Photoshopserver. But I can't find this program
-
IMovie to iWeb viewing problems
Thanks to earlier posts I have now been able to upload a movie onto my MobileMe website, I've done this by opening it in iMovie and going to Share, Media Brower, Mobile and Publish, then doing the approprite thing in the iWeb Inspector. I have not ad
-
Oracle Applications Release 11.0 CD Pack for MS Windows NT
1. Can I install this on Windows 2000 server? 2. If yes, when I try to install, the one hour install pops an error showing, "One hour install requires that the TCPIP Domain name is set" How do I fix this? Please help Regards Madhu
-
Pages and letters with addresses
I'm sorry I can't find how to add names form the address book into a pages document. If this isn't built in "it is seriously missing" if it is I can't find it. I could go on but I know the device (iPad) is limited in power and memory. It just keeps g
-
Nikon D90 images not in import screen
I recently purchased the Nikon D90 and of course I am playing with it this weekend. The images appear fine once imported into Aperture, however, the images do not appear on the import screen. At this point the images are still on the SD card in the c