What's faster  - full outer join or sum a union

Hello,
what do you think it's the best way to bring two tables together? Full outer join (1) or sum over a union (2)?
1.
select a.id nvl(a.x,0) ,nvl(b.y,0) from
a full outer join b
where a.id=b.id
2.
select id, sun(x), sum(y) from
(select id, x,0 y from a
union all
select id, 0 x, y from b )
group by id;
The ids are primary keys and ca. 80% of ids in a are found in b and vice versa.
Both tables have about 20 mio datasets.
Thank for thinking about
Stephan

Like so many things in Oracle, the answer is it depends. Various factors such as resources available (memory, CPU, disk speed etc.), size of the tables, and the indexes available will all influence the performance of a given query.
Having said that, my guess would be that the UNION ALL query would be faster than the full outer join, since ther is less work involved. However, the optimized may be smart enough to re-write the full outer join as a union all.
Another approach which might be worth benchmarking is:
SELECT id, SUM(x), SUM(y)
FROM (SELECT id, SUM(x), 0 y
      FROM a
      GROUP BY id
      UNION ALL
      SELECT id, 0, SUM(y) y
      FROM b
      GROUP BY id)HTH
John

Similar Messages

  • Query with FULL OUTER JOIN , help pleaseeeeeeeeeeee...

    Hi everyone,
    I'm trying to write a query for a report in Oracle SQL, but i just can't figure out how to do it.
    I'm using Oracle 10g release 1.0 database and i execute my queris in SQL* PLUS ( eventually i'm gonna use them in Oracle Report Builder ) .
    here's what i have:
    i have four tables that are used for our inventory application. lets call them INCOMMING , INCOMMING_ITEMS , OUTGOING , OUTGOING_ITEMS.
    as you may have guessed , INCOMMING_ITEMS is the detail table for INCOMMING ( joined by IID column) and also OUTGOING_ITEMS is the detail table for OUTGOING ( joined by OID column ).
    here is the structure of them :
    INCOMMING
    IID varchar2
    CDATE date
    INCOMMING_ITEM
    IID varchar2
    PART_NO number
    QTY number
    OUTGOING
    OID varchar2
    CDATE date
    OUTGOING_ITEM
    OID varchar2
    PART_NO number
    QTY number
    now , the query i want, should return part_no , cdate , sum of OUTGOING qty , sum of INCOMMING qty .
    the result of the query should be sth like this :
    part_no     cdate     O_qty     I_qty
    100     01/05/06     10     0
    100     01/05/07     20     60
    200     01/06/02     0     50
    300     01/06/02     30     40
    this means that for some dates and for some parts, i may not have INCOMMING or OUTGOING data, but if at least one of the 2 last columns has a non-zero data, i should show the row ( like the first and third rows of my example result), and if both have data for the same PART_NO and the same CDATE, both should be showed in the same row. ( like the second row in my example result)
    i tried so much and came up with several huge and also time consuming queries, but then i read abt FULL OUTER JOIN somewhere and tried using that. here is what i came up with :
    SELECT
    PART_NO , CDATE , sum(II.QTY) I_QTY , SUM (OI.QTY) O_QTY
    FROM
         (OUTGOING O INNER JOIN OUTGOING_ITEM OI USING ( OID ) )
    FULL OUTER JOIN
         (INCOMMING I INNER JOIN INCOMMING_ITEM II USING ( IID ) )
    ON ( I.CDATE = O.CDATE AND II.PART_NO = OI.PART_NO)
    WHERE
    I.CDATE = :PARAMETER1
    AND O.CDATE = :PARAMETER1
    GROUP BY
    PART_NO , CDATE
    this query is short and fast , but the results r not what i expected. i mean, although i have used FULL OUTER JOIN in the query , but the results i get r sth like this :
    part_no     cdate     O_qty     I_qty
    100     01/05/07     20     60
    300     01/06/02     30     40
    which means only the rows that has both values are returned.
    any change i make to this query would make the SQL* PLUS hang , like when i use the cartesian product of two large tables, so i guess my changes wheren't in the right direction.
    i think its possible to write this query using FULL OUTER JOIN syntax, but i just can't find it.
    Can anybody pleaseeeeeeeeeeeee help me?
    thanx in advance,
    Maryam.

    Note: I wrote this on the fly -- hope there is no syntax errors, otherwise forgive me -- but you get the idea..
    select
    fromUnionAll.cdate, fromUnionAll.part_no,
    sum(fromUnionAll.O_qty) O_qty,
    sum(fromUnionAll.I_qty) I_qty
    from
    select
    iinner.cdate, iinner.part_no, 0 O_qty, iinner.I_qty
    from
    select
    i.cdate, ii.part_no,
    /* added the case only for the extreme case when there is
    no record anywhere for the given CDATE in INCOMMING_item */
    sum( ( case when ii.qty is not null then ii.qty else 0 end) ) I_qty
    from
    incomming i,
    incomming_item ii
    where
    i.iid = ii.iid (+)
    group by i.cdate, ii.part_no
    ) iinner
    union all
    select
    oinner.cdate, oinner.part_no, oinner.O_qty, 0 I_qty
    from
    select
    o.cdate, oi.part_no,
    /* added the case only for the extreme case when there is
    no record anywhere for the given CDATE in OUTGOING_item */
    sum( ( case when oi.qty is not null then oi.qty else 0 end) ) O_qty
    from
    outgoing o,
    outgoing_item oi
    where
    o.oid = oi.oid (+)
    group by o.cdate, oi.part_no
    ) oinner
    ) fromUnionAll
    group by fromUnionAll.cdate, fromUnionAll.part_no;
    --Samson                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • Full outer join unexpected results

    Warning, long message - I've searched the forums and found nothing similar. I've cut out as much as possible. We have been given the following schema to work with:
    CREATE TABLE CALLS (
    TRUNKIN VARCHAR2 (10),
    TRUNKOUT VARCHAR2 (10),
    DURATION FLOAT)
    Here is some test data:
    insert into calls values(null, 'a', 3);
    insert into calls values(null, 'a', 2);
    insert into calls values('a', null, 1);
    insert into calls values(null, 'a', 0);
    insert into calls values(null, 'a', 0);
    insert into calls values(null, 'a', 7);
    insert into calls values(null, null, 0);
    This is horribly unnormalized, but basically this table represent phone calls. trunkin and trunkout represent the two ends, and duration is length of a call. While obviously every call has two ends, the nulls above represent ends we don't care about in this example.
    The goal is to end up with data that looks like this. In English, we want the in and out summary statistics for each trunk to be summarized into a single row. (Sorry, these are supposed to be columns, but they got wrapped, so I reposted them as rows):
    TRUNKIN a
    IN_CALLS_ATTEMPTED 1
    IN_CALLS_COMPLETED 1
    IN_AVERAGE_DURATION 1
    TRUNKOUT a
    OUT_CALLS_ATTEMPTED 5
    OUT_CALLS_COMPLETED 3
    OUT_AVERAGE_DURATION 4
    Indeed, with the data given above, these are the results returned with the query at the end of this message. However, when I changed the one non-null trunkin value to null, I got very strange results. First, I independently ran the two subqueries. The first of course returns no rows, the second returns 1 with the same out values above; this is exactly what I would expect. However, when I run the full query, I get **5** rows back, each with just the trunkout column set to "a" and **all** other columns set to null. This makes no sense to me. The 5 rows are obviously the 5 rows from the original data set where trunkout = "a", but I'm not full outer joining those; I'm full outer joining the result of the group by, which only has 1 row. But even given that I'm getting 5 rows back, shouldn't all five of those have the remaining out columns filled in with the values above?
    Here is the query:
    select
    from
    SELECT
    trunkin as trunk,
    COUNT(*) AS in_calls_attempted,
    SUM
    CASE
    WHEN duration > 0 THEN 1
    ELSE 0
    END
    ) AS in_calls_completed,
    SUM(duration)/
    SUM
    CASE
    WHEN duration > 0 THEN 1
    ELSE 0
    END
    ) AS in_average_duration
    FROM CALLS
    WHERE trunkin IS NOT NULL
    GROUP BY trunkin
    ) callsin
    full outer join
    SELECT
    trunkout as trunk,
    COUNT(*) AS out_calls_attempted,
    SUM
    CASE
    WHEN duration > 0 THEN 1
    ELSE 0
    END
    ) AS out_calls_completed,
    SUM(duration)/
    SUM
    CASE
    WHEN duration > 0 THEN 1
    ELSE 0
    END
    ) AS out_average_duration
    FROM CALLS
    WHERE trunkout IS NOT NULL
    GROUP BY trunkout
    ) callsout
    on callsin.trunk = callsout.trunk;

    I am not entirely sure why you are getting the results you are, but I strongly suspect that it is a result of outer joining on null columns. I would write the query as follows to avoid the outer join problem. The CASE statements in the outer query around the average duration calulations avoid the divide by zero error that would occur when some trunk has only in or out calls.
    SELECT trunk,SUM(in_calls_attempted) in_calls_attempted,
           SUM(in_calls_completed) in_calls_completed,
           CASE WHEN SUM(in_calls_completed) <> 0 THEN
                SUM(in_duration)/SUM(in_calls_completed)
                ELSE 0 END ave_in_duration,
           SUM(out_calls_attempted) out_calls_attempted,
           SUM(out_calls_completed) out_calls_completed,
           CASE WHEN SUM(out_calls_completed) <> 0 THEN
                SUM(out_duration)/SUM(out_calls_completed)
                ELSE 0 END ave_out_duration
    FROM (
       SELECT trunkin trunk,COUNT(*) in_calls_attempted,
              SUM(CASE WHEN duration > 0 THEN 1 ELSE 0 END) in_calls_completed,
              SUM(duration) in_duration,0 out_calls_attempted,
              0 out_calls_completed,0 out_duration
       FROM calls
       GROUP BY trunkin
       UNION ALL
       SELECT trunkout trunk,0 in_calls_attempted,0 in_calls_completed,
              0 in_duration,COUNT(*) out_calls_attempted,
              SUM(CASE WHEN duration > 0 THEN 1 ELSE 0 END) out_calls_completed,
              SUM(duration) out_duration
       FROM calls
       GROUP BY trunkout)
    GROUP BY trunkTTFN
    John

  • [8i] Need help with full outer join combined with a cross-join....

    I can't figure out how to combine a full outer join with another type of join ... is this possible?
    Here's some create table and insert statements for some basic sample data:
    CREATE TABLE     my_tab1
    (     record_id     NUMBER     NOT NULL     
    ,     workstation     VARCHAR2(4)
    ,     my_value     NUMBER
         CONSTRAINT my_tab1_pk PRIMARY KEY (record_id)
    INSERT INTO     my_tab1
    VALUES(1,'ABCD',10);
    INSERT INTO     my_tab1
    VALUES(2,'ABCD',15);
    INSERT INTO     my_tab1
    VALUES(3,'ABCD',5);
    INSERT INTO     my_tab1
    VALUES(4,'A123',5);
    INSERT INTO     my_tab1
    VALUES(5,'A123',10);
    INSERT INTO     my_tab1
    VALUES(6,'A123',20);
    INSERT INTO     my_tab1
    VALUES(7,'????',5);
    CREATE TABLE     my_tab2
    (     workstation     VARCHAR2(4)
    ,     wkstn_name     VARCHAR2(20)
         CONSTRAINT my_tab2_pk PRIMARY KEY (workstation)
    INSERT INTO     my_tab2
    VALUES('ABCD','WKSTN 1');
    INSERT INTO     my_tab2
    VALUES('A123','WKSTN 2');
    INSERT INTO     my_tab2
    VALUES('B456','WKSTN 3');
    CREATE TABLE     my_tab3
    (     my_nbr1     NUMBER
    ,     my_nbr2     NUMBER
    INSERT INTO     my_tab3
    VALUES(1,2);
    INSERT INTO     my_tab3
    VALUES(2,3);
    INSERT INTO     my_tab3
    VALUES(3,4);And, the results I want to get:
    workstation     sum(my_value)     wkstn_name     my_nbr1     my_nbr2
    ABCD          30          WKSTN 1          1     2
    ABCD          30          WKSTN 1          2     3
    ABCD          30          WKSTN 1          3     4
    A123          35          WKSTN 2          1     2
    A123          35          WKSTN 2          2     3
    A123          35          WKSTN 2          3     4
    B456          0          WKSTN 3          1     2
    B456          0          WKSTN 3          2     3
    B456          0          WKSTN 3          3     4
    ????          5          NULL          1     2
    ????          5          NULL          2     3
    ????          5          NULL          3     4I've tried a number of different things, googled my problem, and no luck yet...
    SELECT     t1.workstation
    ,     SUM(t1.my_value)
    ,     t2.wkstn_name
    ,     t3.my_nbr1
    ,     t3.my_nbr2
    FROM     my_tab1 t1
    ,     my_tab2 t2
    ,     my_tab3 t3
    ...So, what I want is a full outer join of t1 and t2 on workstation, and a cross-join of that with t3. I'm wondering if I can't find any examples of this online because it's not possible....
    Note: I'm stuck dealing with Oracle 8i
    Thanks!!

    Hi,
    The query I posted yesterday is a little more complicated than it needs to be.
    Since my_tab2.workstation is unique, there's no reason to do a separate sub-query like mt1; we can join my_tab1 to my_tab2 and get the SUM all in one sub-query.
    SELECT       foj.workstation
    ,       foj.sum_my_value
    ,       foj.wkstn_name
    ,       mt3.my_nbr1
    ,       mt3.my_nbr2
    FROM       (     -- Begin in-line view foj for full outer join
              SELECT        mt1.workstation
              ,        SUM (mt1.my_value)     AS sum_my_value
              ,        mt2.wkstn_name
              FROM        my_tab1   mt1
              ,        my_tab2   mt2
              WHERE        mt1.workstation     = mt2.workstation (+)
              GROUP BY   mt1.workstation
              ,        mt2.wkstn_name
                    UNION ALL
              SELECT      workstation
              ,      0      AS sum_my_value
              ,      wkstn_name
              FROM      my_tab2
              WHERE      workstation     NOT IN (     -- Begin NOT IN sub-query
                                               SELECT      workstation
                                       FROM      my_tab1
                                       WHERE      workstation     IS NOT NULL
                                     )     -- End NOT IN sub-query
           ) foj     -- End in-line view foj for full outer join
    ,       my_tab3  mt3
    ORDER BY  foj.wkstn_name
    ,       foj.workstation
    ,       mt3.my_nbr1
    ,       mt3.my_nbr2
    ;Thanks for posting the CREATE TABLE and INSERT statements, as well as the very clear desired results!
    user11033437 wrote:
    ... So, what I want is a full outer join of t1 and t2 on workstation, and a cross-join of that with t3. That it, exactly!
    The tricky part is how and when to get SUM (my_value). You might approach this by figuring out exactly what my_tab3 has to be cross-joined to; that is, exactly what should the result set of the full outer join between my_tab1 and my_tab2 look like. To do that, take your desired results, remove the columns that do not come from the full outer join, and remove the duplicate rows. You'll get:
    workstation     sum(my_value)     wkstn_name
    ABCD          30          WKSTN 1          
    A123          35          WKSTN 2          
    B456          0          WKSTN 3          
    ????          5          NULL          So the core of the problem is how to get these results from my_tab1 and my_tab2, which is done in sub-query foj above.
    I tried to use self-documenting names in my code. I hope you can understand it.
    I could spend hours explaining different parts of this query in more detail, but I'm sure I'd waste some of that time explaining things you already understand. If you want an explanation of somthing(s) specific, let me know.

  • Fact vertical capabilities - Full outer Join - How to?

    Hi,
    I have the same problem described in another post: Forcing full outer join between two facts according to common dimensions
    I will use the same example:
    Let's assume 2 fact tables F1 and F2 and 2 dimension D1 and D2.
    Fi is joined to Dj thanks to IDs.
    F1 and F2 have got aggregates sum(mes1), respectively sum(mes2).
    The group by is performed on dim1 for D1 and dim2 for D2.
    The following 2 queries work fine...but separately:
    select dim1, dim2, sum(mes1) from F1, D1, D2 where ... group by dim1, dim2; //7 lines
    select dim1, dim2, sum(mes2) from F2, D1, D2 where ... group by dim1, dim2; //8 lines
    When I try to select dim1, dim2, sum(mes1) and sum(mes2), the following sql is created by the BI server:
    WITH SAWITH0 AS (
    select dim1, dim2, sum(mes1) c3 from F1, D1, D2 where ... group by dim1, dim2
    ), SAWITH1 AS (
    select dim1, dim2, sum(mes2) c3 from F2, D1, D2 where ... group by dim1, dim2
    select ... dim1,
    ... dim2,
    ... SAWITH0.c3,
    ... SAWITH1.c3
    FROM SAWITH0 LEFT OUTER JOIN SAWITH1
    on SAWITH0.dim1=SAWITH1.dim1 and SAWITH0.dim2=SAWITH1.dim2
    I get only 7 lines. It means I miss one line from the second query on F2.
    The solution is to perform a full outer join between both queries..
    The reply was a link to fact vertical capabilities of OBIEE
    (http://gerardnico.com/wiki/dat/obiee/logical_sql/obiee_full_outer_join)
    (http://gerardnico.com/wiki/dat/obiee/bi_server/design/obiee_densification_design_preservation_dimension)
    In this post the solution is to add a dummy fact table to force a crossjoin.
    This solution don't work in my case because I don't need to return all the members of the dimension, I just need to return the dimension member that are joined to both facts..
    if in the example, the dimension have 20 member with the fact vertical capabilities solution my reports will show 20 rows... and I only want to see 8 rows...
    Any Idea?
    Thanks...

    I found what was the real problem:
    I have two diferent physical and logical Facts with 4 common dimensions and 1 dimesion that only affect to the second fact.
    In my report I'm filtering for this last dimension so the OBI use this query (the more restrictive) and made a left join with the second result...
    The problem is what I need is filter only by the column, but I cant do it because I'm using a column selector and I can't do a FILTER USING statement using a dashboard prompt...
    Any Idea?
    Thanks

  • Removing full outer joins

    Hi All,
    I am creating reports from two fact tables. However, in spite of using only inner joins in RPD, obiee is generating full outer joins between two WITH (sub-query factoring) . Is there a way to enforce inner joins.
    Thanks
    Surya

    872073 wrote:
    All the joins in RPD are inner joins. The query generated is similar as follows. The full outer join is automatically created between SAWITH0 SAWITH1
    WITH
    SAWITH0 AS (SELECT sum(T245.QUANTITY_SOLD) AS c1,
    T161.CHANNEL_DESC AS c2
    FROM
    SH.CHANNELS T161,
    SH.SALES T245
    WHERE ( T161.CHANNEL_ID = T245.CHANNEL_ID )
    GROUP BY T161.CHANNEL_DESC),
    SAWITH1 AS (SELECT sum(T168.UNIT_COST) AS c1,
    T161.CHANNEL_DESC AS c2
    FROM
    SH.CHANNELS T161,
    SH.COSTS T168
    WHERE ( T161.CHANNEL_ID = T168.CHANNEL_ID )
    GROUP BY T161.CHANNEL_DESC)
    SELECT DISTINCT case when SAWITH1.c2 IS NOT NULL then SAWITH1.c2 when SAWITH0.c2 IS NOT NULL then SAWITH0.c2 end AS c1,
    SAWITH0.c1 AS c2,
    SAWITH1.c1 AS c3
    FROM
    SAWITH0 FULL OUTER JOIN SAWITH1 ON SAWITH0.c2 = SAWITH1.c2
    ORDER BY c1
    If I change the underlined FULL OUTER JOIN above to just "JOIN", the query returns what I want.
    Edited by: 872073 on Oct 24, 2012 1:14 PMCheck to see if PERF_PREFER_INTERNAL_STITCH_JOIN was turned off in the DB Features.ini file
    The path to the file is Oracle/Middleware/instances/instance1/config/OracleBIServerComponent/coreapplication_obis1/DBFeatures.INI

  • Full outer Join:ORA-01790

    Hi All,
    The issue may be silly, but we cant make it out:
        DB : Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProdWe are running the below query with no issues:
    select t1.text,t2.text text2,t1.line,decode(upper(t1.text),upper(t2.text),1,0) flg
    from
       (select text,row_number() over(order by line) line
        from user_source
       where name = 'COLL_MVIEW_REFRESH_PROC_LBK'
       and replace(trim(text),chr(10)) is not null
       ) t1,
       (select text ,row_number() over(order by line) line
        from user_source
        where name = 'COLL_MVIEW_REFRESH_PROC'
        and trim(replace(text,chr(10))) is not null) t2
    where t1.line = t2.lineBut when trying for an outer join it is giving error like
    ORA-01790: expression must have same datatype as corresponding expressionOuter Join Query:
    select t1.text,t2.text,t1.line,decode(upper(t1.text),upper(t2.text),1,0) flg
    from
       (select text,row_number() over(order by line) line
        from user_source
        where name = 'COLL_MVIEW_REFRESH_PROC_LBK'
        and replace(trim(text),chr(10)) is not null
        ) t1 full outer join
        (select text ,row_number() over(order by line) line
        from user_source
        where name = 'COLL_MVIEW_REFRESH_PROC'
        and trim(replace(text,chr(10))) is not null) t2
    on( t1.line = t2.line )Any idea what is wrong here?
    Thanks,
    Jeneesh

    Not sure what is wrong with your version. It might have to do with row_number not working on an empty row (outer joined).
    How about this alternative?
    The approach is a bit different, but it uses only one access to the user_source view.
    select s.lineNo, min(s.text1) text1, min(s.text2) text2, decode(upper(min(s.text1)), upper(min(s.text2)), 1, 0) flag
    from
    (select decode(u.name, 'COLL_MVIEW_REFRESH_PROC_LBK', u.text) text1
           ,decode(u.name, 'COLL_MVIEW_REFRESH_PROC'
    , u.text) text2
           ,u.name,
            row_number() over (partition by u.name order by u.line) lineNo
    from user_source u
    where u.name in ('COLL_MVIEW_REFRESH_PROC_LBK','COLL_MVIEW_REFRESH_PROC'
    /* and u.TYPE = 'PROCEDURE' */
    and replace(trim(u.text),chr(10)) is not null
    ) s
    group by s.lineNo
    order by s.lineNo;Edited by: Sven W. on Nov 18, 2008 5:24 PM

  • Using full outer join of subqueries named using with clause

    Hi,
    I am trying to create a view which is having 2 subqueries vol1 & vol2 with WITH clause. I am joining those 2 subqueries in the main query with FULL OUTER JOIN.
    When i compile that view in a tool like pl/sql developer, It has been compiled successfully.
    But when i call the view creation script from SQL command prompt, It is throwing error as
    from vol1 FULL JOIN vol2 o ON (vol1.ct_reference = vol2.ct_reference and vol1.table_name = vol2.table_name
    ERROR at line 29:
    ORA-00942: table or view does not exist
    Kindly advise whats going wrong.

    that's line 29. Maybe you get a better idea if you strip your operation of all the unneccessary elements until it works.
    There are some known bugs with subquery factoring (aka with clause) and also with ANSI join syntax, but it is hard to tell what happens here based on your description. But one thing is strange - if it is not a result of formatting (not formatting): I would expect the asterisk beneath the unknown table and not beneath the key word FULL.
    P.S.: my editor makes me think it's rather a proportional font thing. Have I already said that I don't like proportional font for SQL code examples?

  • Help Required in full outer Join

    I feel the below query can be changed to full outer join. But, I've not been able to do so.
    I require your help in changing it to full outer join. My current query is
    SELECT CLAIMNO,'1' INDX FROM D_CLAIM@CMS2PROD
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    MINUS
    SELECT CLAIMNO,'1' FROM D_CLAIM
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    UNION
    SELECT CLAIMNO,'2' FROM D_CLAIM
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    MINUS
    SELECT CLAIMNO,'2' FROM D_CLAIM@cms2prod
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null

    donisback wrote:
    I feel the below query can be changed to full outer join. But, I've not been able to do so.
    I require your help in changing it to full outer join. My current query is
    SELECT CLAIMNO,'1' INDX FROM D_CLAIM@CMS2PROD
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    MINUS
    SELECT CLAIMNO,'1' FROM D_CLAIM
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    UNION
    SELECT CLAIMNO,'2' FROM D_CLAIM
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    MINUS
    SELECT CLAIMNO,'2' FROM D_CLAIM@cms2prod
    WHERE clntsys=76500 and facility=76501 and filecreatedt='18-feb-2011' and fileupdatedt is null
    I do not think that query is doing what you think that it is doing - on first inspection, it was not doing what I thought either due to the order in which the UNION and MINUS operators are performed. If the FILECREATEDT column is defined as a DATE, your query is relying on an implicit date conversion - in such a case, you should replace:
    filecreatedt='18-feb-2011'With:
    filecreatedt=TO_DATE('18-feb-2011','DD-MON-YYYY')Now, building a simple model to explain what is happening, we create two tables with 10 rows each. The first table has C1 values that increase by 2, while the second has C1 values that increase by 3:
    CREATE TABLE T1 AS
    SELECT
      ROWNUM*2 C1,
      TRUNC(SYSDATE)+ROWNUM*2 C2
    FROM
      DUAL
    CONNECT BY
      LEVEL<=10;
    CREATE TABLE T2 AS
    SELECT
      ROWNUM*3 C1,
      TRUNC(SYSDATE)+ROWNUM*3 C2
    FROM
      DUAL
    CONNECT BY
      LEVEL<=10;It appears that the intended result of your query is to obtain a distinct list of those rows that are in each table that are not in both tables - the UNION ALL minus the intersection of the rows in two tables. However, that is not what you are achieving with that query. To demonstrate, the two halves of your query:
    SELECT
      C1,
      C2
    FROM
      T1
    MINUS
    SELECT
      C1,
      C2
    FROM
      T2;
    C1 C2
    2 28-FEB-11
    4 02-MAR-11
    8 06-MAR-11
    10 08-MAR-11
    14 12-MAR-11
    16 14-MAR-11
    20 18-MAR-11
    SELECT
      C1,
      C2
    FROM
      T2
    MINUS
    SELECT
      C1,
      C2
    FROM
      T1;
    C1 C2
    3 01-MAR-11
    9 07-MAR-11
    15 13-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11As can be seen by the above, each half returned 7 rows - there are 7 rows in each table that is not in the other table. Common sense would state that if we UNION these two results (assuming no duplicate values in each table), we would see 14 rows:
    SELECT
      C1,
      C2
    FROM
      T1
    MINUS
    SELECT
      C1,
      C2
    FROM
      T2
    UNION
    SELECT
      C1,
      C2
    FROM
      T2
    MINUS
    SELECT
      C1,
      C2
    FROM
      T1;
    C1 C2
    3 01-MAR-11
    9 07-MAR-11
    15 13-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11Only 7 rows? Let's try again with the help of inline views to control the order in which the MINUS and UNION operators are processed:
    SELECT
    FROM
      (SELECT
        C1,
        C2
      FROM
        T1
      MINUS
      SELECT
        C1,
        C2
      FROM
        T2)
    UNION
    SELECT
    FROM
      (SELECT
        C1,
        C2
      FROM
        T2
      MINUS
      SELECT
        C1,
        C2
      FROM
        T1);
    C1 C2
    2 28-FEB-11
    3 01-MAR-11
    4 02-MAR-11
    8 06-MAR-11
    9 07-MAR-11
    10 08-MAR-11
    14 12-MAR-11
    15 13-MAR-11
    16 14-MAR-11
    20 18-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11Note that the above returned 14 rows. We can do the same using just two outer joins:
    SELECT
      T1.C1,
      T1.C2
    FROM
      T1,
      T2
    WHERE
      T1.C1=T2.C1(+)
      AND T2.C1 IS NULL
    UNION
    SELECT
      T2.C1,
      T2.C2
    FROM
      T1,
      T2
    WHERE
      T2.C1=T1.C1(+)
      AND T1.C1 IS NULL;
    C1 C2
    2 28-FEB-11
    3 01-MAR-11
    4 02-MAR-11
    8 06-MAR-11
    9 07-MAR-11
    10 08-MAR-11
    14 12-MAR-11
    15 13-MAR-11
    16 14-MAR-11
    20 18-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11Or we can do it with a full outer join and a MINUS operator:
    SELECT
      NVL(T1.C1,T2.C1) C1,
      NVL2(T1.C1,T1.C2,T2.C2) C2
    FROM
      T1 FULL OUTER JOIN T2
        ON T1.C1=T2.C1
    MINUS
    SELECT
      T1.C1,
      T1.C2
    FROM
      T1,
      T2
    WHERE
      T1.C1=T2.C1;
    C1 C2
    2 28-FEB-11
    3 01-MAR-11
    4 02-MAR-11
    8 06-MAR-11
    9 07-MAR-11
    10 08-MAR-11
    14 12-MAR-11
    15 13-MAR-11
    16 14-MAR-11
    20 18-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11Or just with a full outer join with a WHERE clause:
    SELECT
      NVL(T1.C1,T2.C1) C1,
      NVL2(T1.C1,T1.C2,T2.C2) C2
    FROM
      T1 FULL OUTER JOIN T2
        ON T1.C1=T2.C1
    WHERE
      (T1.C1 IS NULL
        OR T2.C1 IS NULL);
    C1 C2
    3 01-MAR-11
    9 07-MAR-11
    15 13-MAR-11
    21 19-MAR-11
    24 22-MAR-11
    27 25-MAR-11
    30 28-MAR-11
    8 06-MAR-11
    20 18-MAR-11
    2 28-FEB-11
    10 08-MAR-11
    4 02-MAR-11
    14 12-MAR-11
    16 14-MAR-11With the above knowledge, you should be able to fix your SQL statement to produce the expected results.
    Charles Hooper
    Co-author of "Expert Oracle Practices: Oracle Database Administration from the Oak Table"
    http://hoopercharles.wordpress.com/
    IT Manager/Oracle DBA
    K&M Machine-Fabricating, Inc.

  • Full outer join query giving error

    Hi I have written the below query to get the fields below as an out put but am getting the error missing keyword..am not understanding where did i missed..i have done step by step query analysis..but could not find the error.
    Please help me in resolving the issue.
    Expected output Columns :*
    COUNTRY , TRN_TYPE ,SKU ,BIX_Customer ,PERIOD ,CURRENTSTOCK ,STOCK_VALUE ,SALES ,SALES_VALUE ,TARGET
    Query :_
    select (case when a.country is null then b.country when b.country is null then c.country else a.country end) AS COUNTRY,
    (case when a.Sale_Type is null then b.Stk_type when b.stk_type is null then c.Stk_type else a.Sale_Type end) AS TRN_TYPE,
    (case when a.sku is null then b.sku when b.sku is null then c.sku else a.sku end) AS SKU,
    (case when a.bix_customer is null then b.bix_customer_code when b.bix_customer_code is null then c.bix_customer_code else a.bix_customer end)AS BIX_Customer ,
    (case when a.period is null then TO_number(b.period) when b.period is null then TO_NUMBER(c.period) else a.period end) AS PERIOD,
    nvl(b.CURRENTSTOCK,0) AS CURRENTSTOCK,
    nvl(b.stock_value,0) AS STOCK_VALUE,
    nvl(a.sales,0) AS SALES,
    nvl(a.SALES_VALUE,0) AS SALES_VALUE,
    nvl(c.TARGET_QTY,0) AS TARGET
    from
    (select UPPER(c.cust_country_name) AS COUNTRY,
    DECODE(ds.account_key,7156,'SAMPLE',7157,'BONUS',7485,'SALE') AS Sale_Type,
    substr(i.item_code,7) AS SKU,
    c.bix_customer_code AS BIX_Customer,
    ds.descr as descr ,
    ds.period as period,
    sum(ds.quantity) AS SALES,
    sum(case when ds.local_value is null then ds.euro_value else ds.local_value END) AS SALES_VALUE
    FROM distributor_sales ds, customer c, item i
    where ds.customer_key=c.customer_key
    and ds.item_key= i.item_key
    group by ds.period,
    ds.account_key,
    c.cust_country_name,
    substr(i.item_code,7),
    c.bix_customer_code,
    ds.descr) a
    full outer join
    (SELECT UPPER(b.cust_country_name) AS COUNTRY,
    DECODE(s.stock_type,'SALE','SALE','SALES','SALE','BONUS','BONUS','SAMPLE','SAMPLE') AS Stk_type,
    substr(c.item_code,7) AS SKU,
    s.descr as descr,
    s.period as period,
    b.bix_customer_code,
    sum(s.CLOSING_STOCK) CURRENTSTOCK,
    sum(s.closing_stock*s.cif_price) STOCK_VALUE
    FROM STOCK s, customer b, item c
    WHERE s.customer_key=b.customer_key
    and s.item_key= c.item_key
    group by
    s.descr,
    s.stock_type,
    s.period, b.bix_customer_code,b.cust_country_name,substr(c.item_code,7) ) b
    full outer join
    (SELECT UPPER(cu.cust_country_name) AS COUNTRY,
    DECODE(t.description,'SALES TARGET','SALE') AS Stk_type,
    substr(it.item_code,7) AS SKU,
    t.channel as channel,
    t.period as period,
    cu.bix_customer_code as bix_customer_code,
    sum(t.quantity) TARGET_QTY
    FROM sales_target t, customer cu, item it
    WHERE t.customer_key=cu.customer_key
    and t.item_key= it.item_key
    group by
    t.channel,
    t.description,
    t.period, cu.bix_customer_code,cu.cust_country_name,substr(it.item_code,7) ) c
    on a.SKU=b.SKU
    and a.sku=c.SKU
    and b.sku=c.SKU
    and a.BIX_Customer=b.bix_customer_code
    and a.BIX_Customer=c.bix_customer_code
    and b.bix_customer_code=c.bix_customer_code
    and a.Sale_Type=b.Stk_type
    and a.Sale_Type=c.Stk_type
    and b.Stk_type=c.Stk_type
    and a.descr=b.descr
    and b.descr=c.channel
    and a.descr=c.channel
    and a.country=b.country
    and a.country=c.COUNTRY
    and b.country=c.COUNTRY
    and a.period=b.period
    and a.period=c.period
    and b.period=c.period;

    <tt>Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production</tt>
    You must be aware that you must cascade full outer joins
    with
    t1 as
    (select 1 key,1.1 data from dual union all
    select 3,1.3 from dual union all
    select 6,1.6 from dual union all
    select 7,1.7 from dual
    t2 as
    (select 2 key,2.2 data from dual union all
    select 3,2.3 from dual union all
    select 4,2.4 from dual union all
    select 6,2.6 from dual
    t3 as
    (select 4 key,3.4 data from dual union all
    select 5,3.5 from dual union all
    select 6,3.6 from dual union all
    select 7,3.7 from dual
    select nvl(x.key,t3.key) key,
           x.data_1,
           x.data_2,
           t3.data data_3
      from (select nvl(t1.key,t2.key) key,
                   t1.data data_1,
                   t2.data data_2
              from t1
                   full outer join
                   t2
                on t1.key = t2.key
           ) x
           full outer join
           t3
        on t3.key = x.key
    order by keyunless you can live with duplicate key rows you cannot avoid whenever all table pairs contain common keys (try the below using data from above)
    select coalesce(t1.key,t2.key,t3.key) key,
           t1.data data_1,
           t2.data data_2,
           t3.data data_3
      from t1
           full outer join
           t2
        on t1.key = t2.key
           full outer join
           t3
        on t3.key = t1.key
       and t3.key = t2.key
    order by key
    select coalesce(t1.key,t2.key,t3.key) key,
           t1.data data_1,
           t2.data data_2,
           t3.data data_3
      from t2
           full outer join
           t3
        on t2.key = t3.key
           full outer join
           t1
        on t1.key = t2.key
       and t1.key = t3.key
    order by key
    select coalesce(t1.key,t2.key,t3.key) key,
           t1.data data_1,
           t2.data data_2,
           t3.data data_3
      from t1
           full outer join
           t3
        on t1.key = t3.key
           full outer join
           t2
        on t2.key = t1.key
       and t2.key = t3.key
    order by keyRegards
    Etbin
    Edited by: Etbin on 10.4.2013 9:53
    If you're after
    select *
      from (select *
              from (select *
                      from t1
                   ) a
                   full outer join
                   (select *
                      from t2
                   ) b
                on t1.key = t2.key
           ) x
           full outer join
           t3
        on t3.key = x.key
    order by keyyou're presently at
    select *
      from (
                   (select *
                      from t1
                   ) a
                   full outer join
                   (select *
                      from t2
                   ) b
                on t1.key = t2.key
           ) x
           full outer join
           t3
        on t3.key = x.key
    order by keyORA-00933: SQL command not properly ended

  • Full Outer Join Help Needed

    Hi All,
    I am new to crystal and my sql.
    l have 2 command objects in that i have a common column pos_no.Now i need to apply Fullouterjoin between pos_no,but in crystal we don,t have that option.
    So i saw some threads that we need to apply leftouterjoin union rightouterjoin to get FOJ in db level ,i tried ,but i don't have much knowledge in my sql.So can any one please apply FOJ between Pos_no of these two queries.
    Please help me i strucked here
    1st Query:
    select
    MIN(till_close.start_transaction_id) AS start_trans_id,
    MAX(till_close.end_transaction_id) AS end_trans_id,
    pos_config.pos_no,
    pos_config.name AS pos_name,
    SUM(transaction_tender.amount) AS EodDeposit
    FROM
    till_close
    LEFT OUTER JOIN employee ON (till_close.employee_id = employee.employee_id)
    INNER JOIN pos_config ON (till_close.pos_config_id = pos_config.pos_config_id)
    INNER JOIN transaction_tender ON (till_close.end_transaction_id = transaction_tender.transaction_id)
    INNER JOIN media_type ON (transaction_tender.media_type_id = media_type.media_type_id)
    WHERE
      DATE_FORMAT(till_close.transaction_date,'%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE(?,'%d/%m/%Y'),'%d/%m/%Y')
    AND transaction_tender.media_type_id NOT IN (10000)
    GROUP BY
    pos_config.pos_no
    ORDER BY
    pos_config.pos_no
    2nd Query:
    select
    pos_config.pos_no,
    pos_config.name AS pos_name,
    SUM(CASE WHEN transaction.transaction_type_id=7 AND ((SELECT COUNT(transaction_id) FROM transaction_tender WHERE transaction_id = transaction.transaction_id  AND media_type_id IN (SELECT media_type_id FROM media_type WHERE tender_type_id=12) AND amount < 0 )>0) THEN 0
      WHEN  transaction_tender.balance < 0
      THEN transaction_tender.amount
      ELSE (transaction_tender.amount - transaction_tender.balance)
      END) AS net
    FROM
    TRANSACTION
    INNER JOIN transaction_tender ON (transaction.transaction_id = transaction_tender.transaction_id)
    INNER JOIN media_type ON (transaction_tender.media_type_id = media_type.media_type_id)
    INNER JOIN pos_config ON (transaction.pos_config_id = pos_config.pos_config_id)
    WHERE
    transaction.transaction_date = DATE_FORMAT(STR_TO_DATE(?, '%d/%m/%Y'), '%Y-%m-%d')
    AND transaction.transaction_type_id IN (1,5,7)
    AND transaction.transaction_status_id = 3
    AND transaction.is_training_mode = 0
    GROUP BY
    pos_config.pos_no

    hi Divya,
    i would definitely take the advice from the folks here on a rewrite of your commands into one command.
    since you've got 2 commands that are bringing back different results you may wish to consider bringing back the results from the 2nd command via a sub-query.
    the general idea of the query is below, but you'll need to consult your online help for your database and or your dba for the correct syntax for your situation.
    notes:
    1) the subselect is in the bold font and is defined as a result set in the join...again, please consult your database help or the appropriated forum for your database as your syntax may vary
    2) the fields in the subquery are then referenced in the select clause using the TT alias assigned to the result set in the join
    3) the full outer join i guessed that you wanted on the two pos_no fields
    4) if you do try to do this method and are looking on your database forum, do a search on "subquery multiple columns"
    cheers,
    jamie
    select
    MIN(till_close.start_transaction_id) AS start_trans_id,
    MAX(till_close.end_transaction_id) AS end_trans_id,
    pos_config.pos_no AS PC_pos_no,
    pos_config.name AS pos_name AS PC_pos_name,
    SUM(transaction_tender.amount) AS EodDeposit,
    TT.pos_no AS TT_pos_no,
    TT.pos_name AS TT_pos_name,
    TT.net
    FROM
    till_close
    LEFT OUTER JOIN employee ON (till_close.employee_id = employee.employee_id)
    INNER JOIN pos_config ON (till_close.pos_config_id = pos_config.pos_config_id)
    INNER JOIN transaction_tender ON (till_close.end_transaction_id = transaction_tender.transaction_id)
    INNER JOIN media_type ON (transaction_tender.media_type_id = media_type.media_type_id)
    FULL OUTER JOIN
    (select
    pos_config.pos_no,
    pos_config.pos_name,
    SUM(CASE WHEN transaction.transaction_type_id=7 AND ((SELECT COUNT(transaction_id) FROM transaction_tender WHERE transaction_id = transaction.transaction_id  AND media_type_id IN (SELECT media_type_id FROM media_type WHERE tender_type_id=12) AND amount < 0 )>0) THEN 0
      WHEN  transaction_tender.balance < 0
      THEN transaction_tender.amount
      ELSE (transaction_tender.amount - transaction_tender.balance)
      END) AS net
    FROM
    TRANSACTION
    INNER JOIN transaction_tender ON (transaction.transaction_id = transaction_tender.transaction_id)
    INNER JOIN media_type ON (transaction_tender.media_type_id = media_type.media_type_id)
    INNER JOIN pos_config ON (transaction.pos_config_id = pos_config.pos_config_id)
    WHERE
    transaction.transaction_date = DATE_FORMAT(STR_TO_DATE(?, '%d/%m/%Y'), '%Y-%m-%d')
    AND transaction.transaction_type_id IN (1,5,7)
    AND transaction.transaction_status_id = 3
    AND transaction.is_training_mode = 0
    GROUP BY
    pos_config.pos_no) AS TT
    ON TT.pos_no =  pos_config.pos_no
    WHERE
      DATE_FORMAT(till_close.transaction_date,'%d/%m/%Y') = DATE_FORMAT(STR_TO_DATE(?,'%d/%m/%Y'),'%d/%m/%Y')
    AND transaction_tender.media_type_id NOT IN (10000)
    GROUP BY
    pos_config.pos_no
    ORDER BY
    pos_config.pos_no

  • Oracle 8i Full Outer Join Syntax

    Can someone please help me run this on Oracle 8i:
    SELECT
    R.CUSTOMER_NUM,
    R.SURNAME_NM,
    R.FIRST_NM,
    R.STREET_NM,
    R.PROV_CD,
    R.CITY_NM,
    R.POSTL_CD,
    W.ADDR_TWO_DESC,
    C.RTL_CO_NUM,
    C.CARD_NUM
    FROM
    RTL_CUST R
    FULL OUTER JOIN WHLSL_CUST W ON (R.CUST_NUM = W.CUST_NUM)
    FULL OUTER JOIN CUSTOMER_CARD C ON (T.CUST_NUM = C.CUST_NUM)
    I only know the ANSI syntax. Whats the old one?

    Is this correct:
    SELECT R.CUST_NUM, R.SURNAME_NM, R.FIRST_NM, R.STREET_NM, R.PROV_CD, R.CITY_NM, R.POSTL_CD, W.ADDR_TWO_DESC, NULL AS RTL_CO_NUM, NULL AS CARD_NUM
    FROM CCD_RTL_CUST R, CCD_WHLSL_CUST W WHERE R.CUST_NUM (+) = W.CUST_NUM
    UNION
    SELECT R.CUST_NUM, R.SURNAME_NM, R.FIRST_NM, R.STREET_NM, R.PROV_CD, R.CITY_NM, R.POSTL_CD, W.ADDR_TWO_DESC, NULL AS RTL_CO_NUM, NULL AS CARD_NUM
    FROM CCD_RTL_CUST R, CCD_WHLSL_CUST W WHERE R.CUST_NUM = W.CUST_NUM (+)
    UNION
    SELECT R.CUST_NUM, R.SURNAME_NM, R.FIRST_NM, R.STREET_NM, R.PROV_CD, R.CITY_NM, R.POSTL_CD, NULL AS ADDR_TWO_DESC, C.RTL_CO_NUM, C.CARD_NUM
    FROM CCD_RTL_CUST R, CUST_CARD C WHERE R.CUST_NUM (+) = C.CUST_NUM
    UNION
    SELECT R.CUST_NUM, R.SURNAME_NM, R.FIRST_NM, R.STREET_NM, R.PROV_CD, R.CITY_NM, R.POSTL_CD, NULL AS , C.RTL_CO_NUM, C.CARD_NUM
    FROM CCD_RTL_CUST R, CUST_CARD C WHERE R.CUST_NUM = C.CUST_NUM (+);

  • SQL Query Assistance Required for Full Outer Join

    Hi,
    Lets say I have two tables, i.e:
    TAB_A (colA1, colA2, colA3, colA4)
    TAB_B (colB1, colB2, colB3, colB4) where colB2 is a FK to colA1
    I am after an SQL query that will cater for both the following two scenarios.
    Scenario 1:
    TAB_A has two rows of data, i.e
    (1, ABC100, 1, WG_A)
    (2, ABC100, 2, WG_B)
    TAB_B has one row of data, i.e
    (1, 1, EMP_222, 4)
    I use the following SQL:
    select a.*, b.*
    from tab_a a FULL OUTER JOIN tab_b b ON (a.colA1 = b.colB2)
    where a.colA2 = 'ABC100'
    This returns two rows:
    1, ABC100, 1, WG_A, 1, 1, EMP_222, 4
    2, ABC100, 2, WG_B
    Now, what I actually would like my query to do is actually only return the row where a tab_b record exists, i.e, should only return one record:
    1, ABC100, 1, WG_A, 1, 1, EMP_222, 4
    This I can achieve by using a RIGHT OUTER JOIN instead above, but this causes issue with my scenario 2, which is the following set-up
    Scenario 2:
    TAB_A has only one row of data this time, i.e
    (2, ABC100, 2, WG_B)
    TAB_B has no data at all this time
    This returns no rows but I actually now want this single record from tab_a returned.
    I basically require an SQL query that will cater for both the top 2 scenarios, i.e, if a tab_b record exists from the outer join then only return this record along with tab_a data. If a tab_b record doesn't exist, then only return the tab_a record.
    Hope the above makes sense.
    Thanks.

    Is it what you need (not very elegant) ?
    SQL> select * from t_outer;
            ID CODE
             1 100
             2 100
    SQL> select * from t_inner;
    no rows selected
    SQL> with tab1 as (
      2  select a.id a_id, a.code, b.id b_id from t_outer a join t_inner b on
      3  (a.id = b.id and a.code = '100'))
      4  select * from tab1
      5  union all
      6  select a.*, null from t_outer a where not exists (
      7  select 1 from tab1)
      8  and a.code = '100'
      9  /
          A_ID CODE             B_ID
             1 100
             2 100
    SQL> insert into t_inner values(2);
    1 row created.
    SQL> with tab1 as (
      2  select a.id a_id, a.code, b.id b_id from t_outer a join t_inner b on
      3  (a.id = b.id and a.code = '100'))
      4  select * from tab1
      5  union all
      6  select a.*, null from t_outer a where not exists (
      7  select 1 from tab1)
      8  and a.code = '100'
      9  /
          A_ID CODE             B_ID
             2 100                 2
    Rgds.

  • Forcing full outer join between two facts according to common dimensions

    Hi everyone,I have an issue with the way obiee "joins" 2 fact tables regarding according to common dimensions.
    Let's assume 2 fact tables F1 and F2 and 2 dimension D1 and D2.
    Fi is joined to Dj thanks to IDs.
    F1 and F2 have got aggregates sum(mes1), respectively sum(mes2).
    The group by is performed on dim1 for D1 and dim2 for D2.
    The following 2 queries work fine...but separately:
    select dim1, dim2, sum(mes1) from F1, D1, D2 where ... group by dim1, dim2; //7 lines
    select dim1, dim2, sum(mes2) from F2, D1, D2 where ... group by dim1, dim2; //8 lines
    When I try to select dim1, dim2, sum(mes1) and sum(mes2), the following sql is created by the BI server:
    WITH SAWITH0 AS (
    select dim1, dim2, sum(mes1) c3 from F1, D1, D2 where ... group by dim1, dim2
    ), SAWITH1 AS (
    select dim1, dim2, sum(mes2) c3 from F2, D1, D2 where ... group by dim1, dim2
    select ... dim1,
         ... dim2,
         ... SAWITH0.c3,
         ... SAWITH1.c3
    FROM SAWITH0 LEFT OUTER JOIN SAWITH1
         on SAWITH0.dim1=SAWITH1.dim1 and SAWITH0.dim2=SAWITH1.dim2
    I get only 7 lines. It means I miss one line from the second query on F2.
    The solution is to perform a full outer join. (I tried in TOAD and changing LEFT by FULL is ok)
    How can I force the full outer join?
    Thanks a lot!

    If you use the fact vertical capabilities of OBIEE, it will normally perform a full outer join :
    http://gerardnico.com/wiki/dat/obiee/logical_sql/obiee_full_outer_join
    Check here for an example (replace the fact cross join by your second fact table F2)
    http://gerardnico.com/wiki/dat/obiee/bi_server/design/obiee_densification_design_preservation_dimension
    Cheers
    Nico

  • OWB does not allow full outer join

    I got following error (twice) while validating my mapping: "VLD-1506: Invalid Expression: Mixing full and partial outer joins in one mapping is not supported".
    I have following join conditions in my mapping:
    1) INGRP1.DISTRICT_ID = INGRP2.DISTRICT_ID And INGRP1.CHARGE_PERIOD_ID = INGRP2.CHARGE_PERIOD_ID And INGRP1.UTL_ID = INGRP2.UTL_ID
    2) The same
    3) INGRP1.CHARGE_PERIOD_ID (+) = INGRP2.CHARGE_PERIOD_ID (+) And
    INGRP1.DISTRICT_ID (+) = INGRP2.DISTRICT_ID (+) And
    INGRP1.PROVIDER# (+) = INGRP2.PROVIDER# (+)
    I suppose there is not any partial joins here. I tried to make first and second conditions with full outer joins too:
    INGRP1.DISTRICT_ID (+) = INGRP2.DISTRICT_ID (+) And
    INGRP1.CHARGE_PERIOD_ID (+) = INGRP2.CHARGE_PERIOD_ID (+) And
    INGRP1.UTL_ID (+) = INGRP2.UTL_ID (+) And
    INGRP1.DISTRICT_ID IS NOT NULL And
    INGRP2.DISTRICT_ID IS NOT NULL
    If I do this, validation reports the same error, but six times instead of twice.
    If I remove outer joins OWB generates following mapping statement:
    MERGE
    /*+ APPEND PARALLEL(MMB$ACCOUNT, DEFAULT, DEFAULT) */
    INTO
    "MMB$ACCOUNT"
    USING
    (SELECT
    /*+ NO_MERGE */
    "INGRP1"."DISTRICT_ID" "DISTRICT_ID",
    DIC$TIME_RECODER."MONTH_ID" "MONTH_ID",
    "INGRP1"."PROVIDER#" "PROVIDER#",
    "INGRP1"."ACCOUNT_NO" "ACCOUNT_NO",
    "INGRP2"."ACCOUNT_NO" "ACCOUNT_NO_1"
    FROM "DIC$TIME_RECODER" DIC$TIME_RECODER,
    (SELECT
    /*+ DRIVING_SITE("AGG"."AGG_INPUT_SUBQUERY"."FC_CHARGES_1_GKH_REL2_GKH_STAR") */
    "AGG"."CHARGE_PERIOD_ID" "CHARGE_PERIOD_ID",
    "AGG"."DISTRICT_ID$0" "DISTRICT_ID",
    "AGG"."PROVIDER#$0" "PROVIDER#",
    "AGG"."ACCOUNT_NO$0" "ACCOUNT_NO"
    FROM (SELECT
    ("AGG_INPUT_SUBQUERY"."CHARGE_PERIOD_ID$0") "CHARGE_PERIOD_ID",
    ("AGG_INPUT_SUBQUERY"."DISTRICT_ID$1") "DISTRICT_ID$0",
    ("AGG_INPUT_SUBQUERY"."PROVIDER#$1") "PROVIDER#$0",
    COUNT(DISTINCT ("AGG_INPUT_SUBQUERY"."ACCOUNT_NO$1")) "ACCOUNT_NO$0"
    FROM (SELECT
    "INGRP1"."DISTRICT_ID" "DISTRICT_ID$1",
    "INGRP1"."CHARGE_PERIOD_ID" "CHARGE_PERIOD_ID$0",
    DM_UTILITIES_1_GKH_R14554."PROVIDER#" "PROVIDER#$1",
    "FC_CHARGES_1_GKH_REL2_GKH_STAR"."ACCOUNT_NO" "ACCOUNT_NO$1"
    FROM {"FC_CHARGES"@GKH_REL2_GKH_STAR} "FC_CHARGES_1_GKH_REL2_GKH_STAR",
    {"DM_UTILITIES"@GKH_REL2_GKH_STAR} DM_UTILITIES_1_GKH_R14554,
    (SELECT
    "DEDUP"."DISTRICT_ID$2" "DISTRICT_ID",
    "DEDUP"."CHARGE_PERIOD_ID$1" "CHARGE_PERIOD_ID",
    "DEDUP"."UTL_ID" "UTL_ID"
    FROM (SELECT
    DISTINCT
    "FC_CHARGES_GKH_REL2_GKH_STAR"."DISTRICT_ID" "DISTRICT_ID$2",
    "FC_CHARGES_GKH_REL2_GKH_STAR"."CHARGE_PERIOD_ID" "CHARGE_PERIOD_ID$1",
    "FC_CHARGES_GKH_REL2_GKH_STAR"."UTL_ID" "UTL_ID"
    FROM {"FC_CHARGES"@GKH_REL2_GKH_STAR} "FC_CHARGES_GKH_REL2_GKH_STAR" WHERE ( (MAP_DIC$ACCOUNT."DATE_START") <= coalesce ( "FC_CHARGES_GKH_REL2_GKH_STAR"."CHANGED_DATE_#" , "FC_CHARGES_GKH_REL2_GKH_STAR"."CREATED_DATE_#" ) )) "DEDUP" ) "INGRP1" WHERE ( "INGRP1"."DISTRICT_ID" = "FC_CHARGES_1_GKH_REL2_GKH_STAR"."DISTRICT_ID" ) AND
    ( "INGRP1"."CHARGE_PERIOD_ID" = "FC_CHARGES_1_GKH_REL2_GKH_STAR"."CHARGE_PERIOD_ID" ) AND
    ( "INGRP1"."UTL_ID" = "FC_CHARGES_1_GKH_REL2_GKH_STAR"."UTL_ID" ) AND
    ( ( DM_UTILITIES_1_GKH_R14554."UTL_ID" (+) = "INGRP1"."UTL_ID" ) )) "AGG_INPUT_SUBQUERY"
    GROUP BY
    ("AGG_INPUT_SUBQUERY"."DISTRICT_ID$1"), ("AGG_INPUT_SUBQUERY"."CHARGE_PERIOD_ID$0"), ("AGG_INPUT_SUBQUERY"."PROVIDER#$1")) "AGG" ) "INGRP1",
    (SELECT
    /*+ DRIVING_SITE("AGG_1"."AGG_INPUT_SUBQUERY$0"."FC_PAYMENTS_1_GKH_RE143940") */
    "AGG_1"."PROVIDER#$2" "PROVIDER#",
    "AGG_1"."DISTRICT_ID$3" "DISTRICT_ID",
    "AGG_1"."CHARGE_PERIOD_ID$2" "CHARGE_PERIOD_ID",
    "AGG_1"."ACCOUNT_NO$2" "ACCOUNT_NO"
    FROM (SELECT
    ("AGG_INPUT_SUBQUERY$0"."PROVIDER#$3") "PROVIDER#$2",
    ("AGG_INPUT_SUBQUERY$0"."DISTRICT_ID$4") "DISTRICT_ID$3",
    ("AGG_INPUT_SUBQUERY$0"."CHARGE_PERIOD_ID$3") "CHARGE_PERIOD_ID$2",
    COUNT(DISTINCT ("AGG_INPUT_SUBQUERY$0"."ACCOUNT_NO$3")) "ACCOUNT_NO$2"
    FROM (SELECT
    "INGRP1"."DISTRICT_ID" "DISTRICT_ID$4",
    "INGRP1"."CHARGE_PERIOD_ID" "CHARGE_PERIOD_ID$3",
    DM_UTILITIES_GKH_REL2_GKH."PROVIDER#" "PROVIDER#$3",
    "FC_PAYMENTS_1_GKH_RE143940"."ACCOUNT_NO" "ACCOUNT_NO$3"
    FROM {"FC_PAYMENTS"@GKH_REL2_GKH_STAR} "FC_PAYMENTS_1_GKH_RE143940",
    {"DM_UTILITIES"@GKH_REL2_GKH_STAR} DM_UTILITIES_GKH_REL2_GKH,
    (SELECT
    "DEDUP_1"."DISTRICT_ID$5" "DISTRICT_ID",
    "DEDUP_1"."CHARGE_PERIOD_ID$4" "CHARGE_PERIOD_ID",
    "DEDUP_1"."UTL_ID$0" "UTL_ID"
    FROM (SELECT
    DISTINCT
    "FC_PAYMENTS_GKH_REL2_GKH_STAR"."DISTRICT_ID" "DISTRICT_ID$5",
    "FC_PAYMENTS_GKH_REL2_GKH_STAR"."CHARGE_PERIOD_ID" "CHARGE_PERIOD_ID$4",
    "FC_PAYMENTS_GKH_REL2_GKH_STAR"."UTL_ID" "UTL_ID$0"
    FROM {"FC_PAYMENTS"@GKH_REL2_GKH_STAR} "FC_PAYMENTS_GKH_REL2_GKH_STAR" WHERE ( (MAP_DIC$ACCOUNT."DATE_START") <= coalesce ( "FC_PAYMENTS_GKH_REL2_GKH_STAR"."CHANGED_DATE_#" , "FC_PAYMENTS_GKH_REL2_GKH_STAR"."CREATED_DATE_#" ) )) "DEDUP_1" ) "INGRP1" WHERE ( "INGRP1"."DISTRICT_ID" = "FC_PAYMENTS_1_GKH_RE143940"."DISTRICT_ID" ) AND
    ( "INGRP1"."CHARGE_PERIOD_ID" = "FC_PAYMENTS_1_GKH_RE143940"."CHARGE_PERIOD_ID" ) AND
    ( "INGRP1"."UTL_ID" = "FC_PAYMENTS_1_GKH_RE143940"."UTL_ID" ) AND
    ( ( DM_UTILITIES_GKH_REL2_GKH."UTL_ID" (+) = "INGRP1"."UTL_ID" ) )) "AGG_INPUT_SUBQUERY$0"
    GROUP BY
    ("AGG_INPUT_SUBQUERY$0"."DISTRICT_ID$4"), ("AGG_INPUT_SUBQUERY$0"."CHARGE_PERIOD_ID$3"), ("AGG_INPUT_SUBQUERY$0"."PROVIDER#$3")) "AGG_1" ) "INGRP2" WHERE ( "INGRP1"."CHARGE_PERIOD_ID" = "INGRP2"."CHARGE_PERIOD_ID" ) AND
    ( "INGRP1"."DISTRICT_ID" = "INGRP2"."DISTRICT_ID" ) AND
    ( "INGRP1"."PROVIDER#" = "INGRP2"."PROVIDER#" ) AND
    ( ( DIC$TIME_RECODER."PERIOD_ID" (+) = "INGRP1"."CHARGE_PERIOD_ID" ) )
    ) "MERGEQUERY_325"
    ON (
    "MMB$ACCOUNT"."DISTRICT_ID" = "MERGEQUERY_325"."DISTRICT_ID" AND
    "MMB$ACCOUNT"."MONTH_ID" = "MERGEQUERY_325"."MONTH_ID" AND
    "MMB$ACCOUNT"."PROVIDER_ID" = "MERGEQUERY_325"."PROVIDER#" )
    WHEN NOT MATCHED THEN
    INSERT
    ("MMB$ACCOUNT"."DISTRICT_ID",
    "MMB$ACCOUNT"."MONTH_ID",
    "MMB$ACCOUNT"."PROVIDER_ID",
    "MMB$ACCOUNT"."QNT_CHARGED",
    "MMB$ACCOUNT"."QNT_PAID")
    VALUES
    ("MERGEQUERY_325"."DISTRICT_ID",
    "MERGEQUERY_325"."MONTH_ID",
    "MERGEQUERY_325"."PROVIDER#",
    "MERGEQUERY_325"."ACCOUNT_NO",
    "MERGEQUERY_325"."ACCOUNT_NO_1")
    WHEN MATCHED THEN
    UPDATE
    SET
    "QNT_CHARGED" = "MERGEQUERY_325"."ACCOUNT_NO",
    "QNT_PAID" = "MERGEQUERY_325"."ACCOUNT_NO_1";
    What does it mean? Is JOINER's full outer join is incompatible with KEY LOOKUP operator and KL should be replaced with WB_LOOKUP_NUM?

    Sanders,
    Key lookup always does a partial outer join. When the full outer join and partial outer join conditions are put together, there is no available syntax to facilitate it.
    The way to this to generate the join operator (with full outer join) first in a subquery, then generate the key lookup as the outer query. Or the other way around, first the key lookup then the full outer join. The important part is that the key lookup can't be merged into the FROM-list.
    So there are two workarounds. One is what you already pointed out, using WB_LOOKUP_NUM.
    The other is to explicitly spell out the key lookup logic in the mapping by introducing a join with the lookup table, like this.
    Change
    Table1
    .......... Join (w/ foj cond.) ---> KeyLookup
    Table2
    to
    Table1
    .......... Join (w/ foj cond)
    Table2 ........................ Join (w/ poj cond.) ---> Lookup table
    Nikolai Rochnik

Maybe you are looking for