Outer Join (select) statement

hI
Im BW-Consultant. I have two tables with some fileds.
ZTABLE1 ---> MATNR, PRCTR, BUKRS, LIGNG, MATGR.And this table has 5-materials
ZTABLE2 --> MATNR, PRCTR, BUKRS, FKMNG, VERID. And this table has 10-materials.
These two tables(ZTABLE1, ZTABLE2) has 3-materials are common.
But i want all 15-materials in an another table ZTABLE3. So how can i write an <b>outer join statement.</b> .
Please give the OuterJoinCode(select statement) to get all 15-materials
regards
kumar

Example
SELECT KNA1~KUNNR KNA1~ADRNR ADR6~SMTP_ADDR
INTO (A, B, C)
FROM KNA1 LEFT OUTER JOIN ADR6
ON KNA1~ADRNR = ADR6~ADDRNUMBER
WHERE KUNNR BETWEEN '0000000000' AND '0000500000'.
DATA: BEGIN OF wa,
        carrid   TYPE scarr-carrid,
        carrname TYPE scarr-carrname,
        connid   TYPE spfli-connid,
      END OF wa,
      itab LIKE SORTED TABLE OF wa
                WITH NON-UNIQUE KEY carrid.
SELECT s~carrid s~carrname p~connid
  INTO CORRESPONDING FIELDS OF TABLE itab
  FROM scarr AS s
       LEFT OUTER JOIN spfli AS p ON s~carrid   =  p~carrid AND
                                     p~cityfrom = 'FRANKFURT'.
LOOP AT itab INTO wa.
  WRITE: / wa-carrid, wa-carrname, wa-connid.
ENDLOOP.
A

Similar Messages

  • How to do outer join select query for an APEX report

    Hello everyone,
    I am Ann.
    I have one select statement that calculate the statistics for one month(October 2012 in this example)
    select ph.phase_number
    , sum ( (case
    WHEN ph.date_finished IS NULL OR ph.date_finished > last_day(TO_DATE('Oct 2012','MON YYYY'))
    THEN last_day(TO_DATE('Oct 2012','MON YYYY'))
    ELSE ph.date_finished
    END )
    - ph.date_started + 1) / count(def.def_id) as avg_days
    from phase_membership ph
    inner join court_engagement ce on ph.mpm_eng_id = ce.engagement_id
    inner join defendant def on ce.defendant_id = def.def_id
    where def.active = 1
    and ph.date_started <= last_day(TO_DATE('Oct 2012','MON YYYY'))
    and ph.active = 1
    and UPPER(ce.court_name) LIKE '%'
    group by rollup(phase_number)
    Result is as below
    Phase_Number     AVG_DAYS
    Phase One     8.6666666666666667
    Phase Two     14.6
    Phase Three     12
         11.4615365
    I have other select list mainly list the months between two date value.
    select to_char(which_month, 'MON YYYY') as display_month
    from (
    select add_months(to_date('Aug 2012','MON YYYY'), rownum-1) which_month
    from all_objects
    where
    rownum <= months_between(to_date('Oct 2012','MON YYYY'), add_months(to_date('Aug 2012','MON YYYY'), -1))
    order by which_month )
    Query result is as below
    DISPLAY_MONTH
    AUG 2012
    SEP 2012
    OCT 2012
    Is there any way that I can join these two select statement above to generate a result like:
    Month          Phase Number     Avg days
    Aug 2012     Phase One     8.666
    Sep 2012     Phase One     7.66
    Oct 2012     Phase One     5.66
    Aug 2012     Phase Two     8.666
    Sep 2012     Phase Two     7.66
    Oct 2012     Phase Two     5.66
    Aug 2012     Phase Three     8.666
    Sep 2012     Phase Three     7.66
    Oct 2012     Phase Three     5.66
    Or
    Month          Phase Number     Avg days
    Aug 2012     Phase One     8.666
    Aug 2012     Phase Two     7.66
    Aug 2012     Phase Three     5.66
    Sep 2012     Phase One     8.666
    Sep 2012     Phase Two     7.66
    Sep 2012     Phase Three     5.66
    Oct 2012     Phase One     8.666
    Oct 2012     Phase Two     7.66
    Oct 2012     Phase Three     5.66
    And it can be order by either Phase Number or Month.
    My other colleague suggest I should use an left outer join but after trying so many ways, I am still stuck.
    One of the select I tried is
    select a.display_month,b.* from (
    select to_char(which_month, 'MON YYYY') as display_month
    from (
    select add_months(to_date('Aug 2012','MON YYYY'), rownum-1) which_month
    from all_objects
    where
    rownum <= months_between(to_date('Oct 2012','MON YYYY'), add_months(to_date('Aug 2012','MON YYYY'), -1))
    order by which_month )) a left outer join
    ( select to_char(ph.date_finished,'MON YYYY') as join_month, ph.phase_number
    , sum ( (case
    WHEN ph.date_finished IS NULL OR ph.date_finished > last_day(TO_DATE(a.display_month,'MON YYYY'))
    THEN last_day(TO_DATE(a.display_month,'MON YYYY'))
    ELSE ph.date_finished
    END )
    - ph.date_started + 1) / count(def.def_id) as avg_days
    from phase_membership ph
    inner join court_engagement ce on ph.mpm_eng_id = ce.engagement_id
    inner join defendant def on ce.defendant_id = def.def_id
    where def.active = 1
    and ph.date_started <= last_day(TO_DATE(a.display_month,'MON YYYY'))
    and ph.active = 1
    and UPPER(ce.court_name) LIKE '%'
    group by to_char(ph.date_finished,'MON YYYY') , rollup(phase_number)) b
    on a.display_month = b.join_month
    but then I get an error
    SQL Error: ORA-00904: "A"."DISPLAY_MONTH": invalid identifier
    I need to display a report on APEX with option for people to download at least CSV format.
    I already have 1 inteactive report in the page, so don’t think can add another interactive report without using the iframe trick.
    If any of you have any ideas, please help.
    Thanks a lot.
    Ann

    First of all, a huge thanks for following this Frank.
    I have just started working here, I think the Oracle version is 11g, but not sure.
    To run Oracle APEX version 4, I think they must have at least 10g R2.
    This report is a bit challenging for me.I has never worked with PARTITION before.
    About the select query you suggested, I run , and it seems working fine, but if I try this,
    it return error ORA-01843: not a valid month
    DEFINE startmonth = "Aug 2012";
    DEFINE endmonth   = "Oct 2012";
    WITH     all_months     AS
         select add_months(to_date('&startmonth','MON YYYY'), rownum-1) AS which_month
         ,      add_months(to_date('&startmonth','MON YYYY'), rownum  ) AS next_month
         from all_objects
         where
         rownum <= months_between(to_date('&endmonth','MON YYYY'), add_months(to_date('&startmonth','MON YYYY'), -1))
    select TO_CHAR (am.which_month, 'Mon YYYY')     AS month
    ,      ph.phase_number
    , sum ( (case
    WHEN ph.date_finished IS NULL OR ph.date_finished > last_day(TO_DATE(am.which_month,'MON YYYY'))
    THEN last_day(TO_DATE(am.which_month,'MON YYYY'))
    ELSE ph.date_finished
    END )
    - ph.date_started + 1) / count(def.def_id) as avg_days
    FROM           all_months          am
    LEFT OUTER JOIN  phase_membership  ph  PARTITION BY (ph.phase_number)
                                        ON  am.which_month <= ph.date_started
                               AND am.next_month  >  ph.date_started
                               AND ph.date_started <= last_day(TO_DATE(am.which_month,'MON YYYY'))  -- May not be needed
                               AND ph.active = 1
    LEFT OUTER join  court_engagement  ce  on  ph.mpm_eng_id = ce.engagement_id
                                        and ce.court_name IS NOT NULL  -- or something involving LIKE
    LEFT OUTER join  defendant         def on  ce.defendant_id = def.def_id
                                        AND def.active = 1
    group by rollup(phase_number, am.which_month)
    ORDER BY  am.which_month
    ,            ph.phase_number
    ;Here is the shorted versions of the three tables:
    A_DEFENDANT, A_ENGAGEMENT, A_PHASE_MEMBERSHIP
    CREATE TABLE "A_DEFENDANT"
        "DEF_ID"     NUMBER NOT NULL ENABLE,
        "FIRST_NAME" VARCHAR2(50 BYTE),
        "SURNAME"    VARCHAR2(20 BYTE) NOT NULL ENABLE,
        "DOB" DATE NOT NULL ENABLE,
        "ACTIVE" NUMBER(2,0) DEFAULT 1 NOT NULL ENABLE,
        CONSTRAINT "A_DEFENDANT_PK" PRIMARY KEY ("DEF_ID"))
    Sample Data
    Insert into A_DEFENDANT (DEF_ID,FIRST_NAME,SURNAME,DOB,ACTIVE) values (101,'Joe','Bloggs',to_date('12/12/99','DD/MM/RR'),1);
    Insert into A_DEFENDANT (DEF_ID,FIRST_NAME,SURNAME,DOB,ACTIVE) values (102,'John','Smith',to_date('20/05/00','DD/MM/RR'),1);
    Insert into A_DEFENDANT (DEF_ID,FIRST_NAME,SURNAME,DOB,ACTIVE) values (103,'Jane','Black',to_date('15/02/98','DD/MM/RR'),1);
    Insert into A_DEFENDANT (DEF_ID,FIRST_NAME,SURNAME,DOB,ACTIVE) values (104,'Minnie','Mouse',to_date('13/12/88','DD/MM/RR'),0);
    Insert into A_DEFENDANT (DEF_ID,FIRST_NAME,SURNAME,DOB,ACTIVE) values (105,'Daisy','Duck',to_date('05/08/00','DD/MM/RR'),1);
    CREATE TABLE "A_ENGAGEMENT"
        "ENGAGEMENT_ID" NUMBER NOT NULL ENABLE,
        "COURT_NAME"    VARCHAR2(50 BYTE) NOT NULL ENABLE,
        "DATE_REFERRED" DATE,
        "DETERMINATION_HEARING_DATE" DATE,
        "DATE_JOINED_COURT" DATE,
        "DATE_TREATMENT_STARTED" DATE,
        "DATE_TERMINATED" DATE,
        "TERMINATION_TYPE" VARCHAR2(50 BYTE),
        "ACTIVE"           NUMBER(2,0) DEFAULT 1 NOT NULL ENABLE,
        "DEFENDANT_ID"     NUMBER,
        CONSTRAINT "A_ENGAGEMENT_PK" PRIMARY KEY ("ENGAGEMENT_ID"))
    Insert into A_ENGAGEMENT (ENGAGEMENT_ID,COURT_NAME,DATE_REFERRED,DETERMINATION_HEARING_DATE,DATE_JOINED_COURT,DATE_TREATMENT_STARTED,DATE_TERMINATED,TERMINATION_TYPE,ACTIVE,DEFENDANT_ID) values (1,'AA',to_date('12/08/12','DD/MM/RR'),null,to_date('12/08/12','DD/MM/RR'),null,null,null,1,101);
    Insert into A_ENGAGEMENT (ENGAGEMENT_ID,COURT_NAME,DATE_REFERRED,DETERMINATION_HEARING_DATE,DATE_JOINED_COURT,DATE_TREATMENT_STARTED,DATE_TERMINATED,TERMINATION_TYPE,ACTIVE,DEFENDANT_ID) values (2,'BB',to_date('01/09/12','DD/MM/RR'),null,to_date('02/09/12','DD/MM/RR'),null,null,null,1,102);
    Insert into A_ENGAGEMENT (ENGAGEMENT_ID,COURT_NAME,DATE_REFERRED,DETERMINATION_HEARING_DATE,DATE_JOINED_COURT,DATE_TREATMENT_STARTED,DATE_TERMINATED,TERMINATION_TYPE,ACTIVE,DEFENDANT_ID) values (3,'AA',to_date('02/09/12','DD/MM/RR'),null,to_date('15/09/12','DD/MM/RR'),null,null,null,1,103);
    Insert into A_ENGAGEMENT (ENGAGEMENT_ID,COURT_NAME,DATE_REFERRED,DETERMINATION_HEARING_DATE,DATE_JOINED_COURT,DATE_TREATMENT_STARTED,DATE_TERMINATED,TERMINATION_TYPE,ACTIVE,DEFENDANT_ID) values (4,'BB',to_date('01/10/12','DD/MM/RR'),null,to_date('02/10/12','DD/MM/RR'),null,null,null,1,105);
    CREATE TABLE "A_PHASE_MEMBERSHIP"
        "MPM_ID"       NUMBER NOT NULL ENABLE,
        "MPM_ENG_ID"   NUMBER NOT NULL ENABLE,
        "PHASE_NUMBER" VARCHAR2(50 BYTE),
        "DATE_STARTED" DATE NOT NULL ENABLE,
        "DATE_FINISHED" DATE,
        "NOTES"  VARCHAR2(2000 BYTE),
        "ACTIVE" NUMBER(2,0) DEFAULT 1 NOT NULL ENABLE,
        CONSTRAINT "A_PHASE_MEMBERSHIP_PK" PRIMARY KEY ("MPM_ID"))
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (1,1,'PHASE ONE',to_date('15/09/12','DD/MM/RR'),to_date('20/09/12','DD/MM/RR'),null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (2,1,'PHASE TWO',to_date('21/09/12','DD/MM/RR'),to_date('29/09/12','DD/MM/RR'),null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (3,2,'PHASE ONE',to_date('12/09/12','DD/MM/RR'),null,null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (4,3,'PHASE ONE',to_date('20/09/12','DD/MM/RR'),to_date('01/10/12','DD/MM/RR'),null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (5,3,'PHASE TWO',to_date('02/10/12','DD/MM/RR'),to_date('15/10/12','DD/MM/RR'),null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (6,4,'PHASE ONE',to_date('03/10/12','DD/MM/RR'),to_date('10/10/12','DD/MM/RR'),null,1);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (7,3,'PHASE THREE',to_date('17/10/12','DD/MM/RR'),null,null,0);
    Insert into A_PHASE_MEMBERSHIP (MPM_ID,MPM_ENG_ID,PHASE_NUMBER,DATE_STARTED,DATE_FINISHED,NOTES,ACTIVE) values (8,1,'PHASE THREE',to_date('30/09/12','DD/MM/RR'),to_date('16/10/12','DD/MM/RR'),null,1);
    The requirements are:
    The user must be able to request the extract for one or more calendar months, e.g.
    May 2013
    May 2013 – Sep 2013.
    The file must contain a separate row for each calendar month in the requested range. Each row must contain the statistics computed for that calendar month.
    The file must also include a row of totals.
    The user must be able to request the extract for either Waitakere or Auckland or Consolidated (both courts’ statistics accumulated).
    Then the part that I am stuck is
    For each monitoring phase:
    Phase name (e.g. “Phase One”)
    Avg_time_in_phase_all_particip
    for each phase name,
    Add up days in each “phase name” Monitoring Phase, calculated as:
    If Monitoring Phase.Date Finished is NULL or > month end date,
    +(*Month end date* Minus Monitoring Phase.Date Started Plus 1)+
    Otherwise (phase is complete)
    +(Monitoring Phase.Date Finished Minus Monitoring Phase.Date Started Plus 1.)+
    Divide by the numbers of all participants who have engaged in “phase name”.
    This is the words of the Business Analyst,
    I try to do as required but still struggle to identify end_month for the above formula to display for the range of months.
    Of course, I can write two nested cursor. The first one run the list of month, then for each month, run the parameterised report.
    But I prefer if possible just use SQL statements, or at least a PL/SQL but return a query.
    With this way, I can create an APEX report, and use their CSV Extract function.
    Yes, you are right, court_name is one of the selection parameters.
    And the statistics is not exactly for one month. It is kind of trying to identify all phases that are running through the specified month (even phase.date_started is before the month start).
    This is the reason why I put the condition AND ph.date_started <= last_day(TO_DATE('Oct 2012','MON YYYY')) (otherwise I get negative avg_days)
    User can choose either one court "AA" or "BB" or combined which is all figures.
    Sorry for bombarding you a lot of information.
    Thanks a lot, again.
    Edited by: Ann586341 on Oct 29, 2012 9:57 PM
    Edited by: Ann586341 on Oct 29, 2012 9:59 PM

  • How to get the inserted row primary key with out  using select statement

    how to return the primary key of inserted row ,with out using select statement
    Edited by: 849614 on Apr 4, 2011 6:13 AM

    yes thanks to all ,who helped me .its working fine
    getGeneratedKeys
    String hh = "INSERT INTO DIPOFFERTE (DIPOFFERTEID,AUDITUSERIDMODIFIED)VALUES(DIPOFFERTE_SEQ.nextval,?)";
              String generatedColumns[] = {"DIPOFFERTEID"};
              PreparedStatement preparedStatement = null;
              try {
                   //String gen[] = {"DIPOFFERTEID"};
                   PreparedStatement pstmt = conn.prepareStatement(hh, generatedColumns);
                   pstmt.setLong(1, 1);
                   pstmt.executeUpdate();
                   ResultSet rs = pstmt.getGeneratedKeys();
                   rs.next();
    //               The generated order id
                   long orderId = rs.getLong(1);

  • Dynamic table name in an inner join - select statement

    Hi,
    Please can you let me know if is possible to use a Dynamic table name in an inner join?
    Something like the statement below? (It works in a simple select statement but not in an inner join)
    SELECT  *
         INTO CORRESPONDING FIELDS OF <t_itab>
          FROM <Dynamic table name> INNER JOIN pa0050 ON
          ( <Dynamic table name>pernr =  pa0050pernr )
           WHERE <Dynamic table name>~pernr = it_pernr-l_pernr
           AND pa0050~bdegr = f_bdegr.
    Any help would be apprecited very much.
    Thanks & Regards.

    Hi,
    Check this link.
    [http://help.sap.com/saphelp_nw04/helpdata/en/fc/eb39c4358411d1829f0000e829fbfe/frameset.htm]
    [Re: accessing dynamic internal table's fields??;
    hope it'll help u.
    Regards,
    Sneha.
    Edited by: sneha kumari on Jun 18, 2009 1:57 PM

  • Joining select statements-performance problem

    Here two cases are there.Is it posiible to combine the two cases and make it one? I am using OR in the select statement, performance is very bad, i want to improve it.Is there any chance of avoiding that...
    1.
    select vbeln from vbfa into itab-vbeln where vbelv = final_data-xblnr1
    or vbelv = final_data-xblnr2.
    select single vbeln from vbrk into tabvbrk-vbeln
    where vbeln = itab-vbeln and fkart = 'RTS'.
    if sy-subrc eq 0.
    move tabvbrk-vbeln to final_data-vbeln1.
    modify final_data.
    endif.
    endselect.
    2.
    select vbeln from vbfa into itab-vbeln where vbelv = final_data-xblnr1
    or vbelv = final_data-xblnr2.
    select single vbeln from vbrk into tabvbrk-vbeln
    where vbeln = itab-vbeln and fkart = 'ZTR'.
    if sy-subrc eq 0.
    move tabvbrk-vbeln to final_data-vbeln2.
    modify final_data.
    endif.
    endselect.
    Thanks,
    fractal

    The first main thing is dont use select... endselect.
    select vbeln from vbfa into itab-vbeln where vbelv = final_data-xblnr1
    or vbelv = final_data-xblnr2.
    U can use
    select vbeln from vbfa into
    corresponding fields of table itab
    for all entries in final_data
    where vbelv = final_data-xblnr1
    or   vbelv = final_data-xblnr2.
    Instead of this
    select single vbeln from vbrk into tabvbrk-vbeln
    where vbeln = itab-vbeln and fkart = 'RTS'.
    if sy-subrc eq 0.
    move tabvbrk-vbeln to final_data-vbeln1.
    modify final_data.
    endif.
    endselect.
    Use
    select vbeln from vbrk
            appending table final_data
            where vbeln = itab-vbeln
            and fkart = 'RTS'.
    if sy-subrc eq 0.
    endif.
    Try like this.
    Hope this helps.
    Kindly reward points for the answer which helped u and helped to solve the problem.

  • Outer join vs. 'SELECT in SELECT'

    Hi All,
    I am generally curious about which method to use between a Outer join and 'SELECT in SELECT'. We can have same result with both methods.
    My question is, for real life complex queries, which method is more efficiant? less resource intensive? Any thories you guys have?
    I am on Oracle 10.2 on lunix.
    See my example below
    -- First table
    create table emp
    id   number,
    name varchar2(1000),
    constraint emp_pk primary key ( id )
    -- second table. There will be 1 record, for few of the records in EMP table, in this table
    create table leave
    id     number,
    emp_id number,
    leave_date date,
    constraint leave_pk primary key (id),
    constraint leave_fk foreign key ( emp_id ) references emp
    create index leave_idx_1 on leave ( emp_id ) ;
    -- Populate some sample data in there
    insert into emp (id, name)
    select object_id, object_name from dba_objects where rownum < 10001 ;
    declare
    cursor c1 is
       select id from emp where mod(id,2) = 0 ;
    v_id  number := 1 ;
    v_date DATE := '01-JAN-08';
    begin
      for c2 in c1
      loop
          insert into leave values ( v_id, c2.id, v_date );
          v_id := v_id + 1;
          v_date := v_date + 1;
      end loop;
    end;
    -- Set autotrace
    set autotrace traceonly explain
    -- =================================
    -- Outer join
    -- =================================
    select e.id, e.name, l.id, l.leave_date
    from   emp e, leave l
    where  e.id = l.emp_id (+) ;
    -- ===================================
    -- select in select to get same results as above outer join
    -- ===================================
    select e.id, e.name,
           (select l.id from leave l where l.emp_id = e.id ) leave_id,
           (select l.leave_date from leave l where l.emp_id = e.id ) leave_date
    from   emp e ;My hidden question, how these two methods internally work? in the plan we can only see something like 'hash join right outer' or something like that. But how exactly outer join is executed? how is the result formed?
    I have got following plans for the two methods
    SQL> select e.id, e.name, l.id, l.leave_date
      2  from   emp e, leave l
      3  where  e.id = l.emp_id (+) ;
    Elapsed: 00:00:00.03
    Execution Plan
    Plan hash value: 98076489
    | Id  | Operation             | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT      |       | 10000 |  5371K|    16   (7)| 00:00:01 |
    |*  1 |  HASH JOIN RIGHT OUTER|       | 10000 |  5371K|    16   (7)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL   | LEAVE |  5012 |   171K|     6   (0)| 00:00:01 |
    |   3 |   TABLE ACCESS FULL   | EMP   | 10000 |  5029K|     9   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - access("E"."ID"="L"."EMP_ID"(+))
    Note
       - dynamic sampling used for this statement
    SQL> select e.id, e.name,
      2         (select l.id from leave l where l.emp_id = e.id ) leave_id,
      3         (select l.leave_date from leave l where l.emp_id = e.id ) leave_date
      4  from   emp e ;
    Elapsed: 00:00:00.18
    Execution Plan
    Plan hash value: 2670217481
    | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT            |             | 10000 |  5029K|     9   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| LEAVE       |    50 |  1300 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | LEAVE_IDX_1 |    20 |       |     1   (0)| 00:00:01 |
    |   3 |  TABLE ACCESS BY INDEX ROWID| LEAVE       |    50 |  1100 |     2   (0)| 00:00:01 |
    |*  4 |   INDEX RANGE SCAN          | LEAVE_IDX_1 |    20 |       |     1   (0)| 00:00:01 |
    |   5 |  TABLE ACCESS FULL          | EMP         | 10000 |  5029K|     9   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       2 - access("L"."EMP_ID"=:B1)
       4 - access("L"."EMP_ID"=:B1)
    Note
       - dynamic sampling used for this statementPlease let me know your thoughts.
    Thanks in advance

    A better indicator of performance would be to look at the number of consistent gets that are required to execute the query.
    In my environment:
    SQL> SELECT * FROM V$VERSION;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE    10.2.0.4.0      Production
    TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    SQL> SHOW PARAMETER OPT
    NAME                                 TYPE        VALUE
    filesystemio_options                 string
    object_cache_optimal_size            integer     102400
    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
    plsql_optimize_level                 integer     2The OUTER JOIN produced the following results:
    SQL> select e.id, e.name, l.id, l.leave_date
      2  from   emp e, leave l
      3  where  e.id = l.emp_id (+) ;
    10000 rows selected.
    Execution Plan
    Plan hash value: 98076489
    | Id  | Operation             | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT      |       | 10000 |   380K|     9  (12)| 00:00:01 |
    |*  1 |  HASH JOIN RIGHT OUTER|       | 10000 |   380K|     9  (12)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL   | LEAVE |  5017 | 80272 |     3   (0)| 00:00:01 |
    |   3 |   TABLE ACCESS FULL   | EMP   | 10000 |   224K|     5   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - access("E"."ID"="L"."EMP_ID"(+))
    Statistics
              0  recursive calls
              0  db block gets
            723  consistent gets
              0  physical reads
              0  redo size
         364047  bytes sent via SQL*Net to client
           7672  bytes received via SQL*Net from client
            668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processedThe inline subquery produced these results:
    SQL> select e.id, e.name,
      2         (select l.id from leave l where l.emp_id = e.id ) leave_id,
      3         (select l.leave_date from leave l where l.emp_id = e.id ) leave_dat
      4  from   emp e ;
    10000 rows selected.
    Execution Plan
    Plan hash value: 1706216391
    | Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |       | 10000 |   224K|     5   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS FULL| LEAVE |     1 |     9 |     3   (0)| 00:00:01 |
    |*  2 |  TABLE ACCESS FULL| LEAVE |     1 |    13 |     3   (0)| 00:00:01 |
    |   3 |  TABLE ACCESS FULL| EMP   | 10000 |   224K|     5   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - filter("L"."EMP_ID"=:B1)
       2 - filter("L"."EMP_ID"=:B1)
    Statistics
              0  recursive calls
              0  db block gets
         360705  consistent gets
              0  physical reads
              0  redo size
         364053  bytes sent via SQL*Net to client
           7672  bytes received via SQL*Net from client
            668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processedSee the 723 consistent gets versus 360705? That is a huge difference.
    The second method may be more viable if you create indexes on the columns in the leave table that you are joining to your EMP table.
    For example:
    SQL> CREATE INDEX LEAD_ID_IDX ON LEAVE(EMP_ID, ID, LEAVE_DATE);
    Index created.
    SQL> set autotrace traceonly
    SQL> select e.id, e.name,
      2         (select l.id from leave l where l.emp_id = e.id ) leave_id,
      3         (select l.leave_date from leave l where l.emp_id = e.id ) leave_date
      4  from   emp e ;
    10000 rows selected.
    Execution Plan
    Plan hash value: 1822800249
    | Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |             | 10000 |   224K|     5   (0)| 00:00:01 |
    |*  1 |  INDEX RANGE SCAN | LEAD_ID_IDX |     1 |     9 |     2   (0)| 00:00:01 |
    |*  2 |  INDEX RANGE SCAN | LEAD_ID_IDX |     1 |    13 |     2   (0)| 00:00:01 |
    |   3 |  TABLE ACCESS FULL| EMP         | 10000 |   224K|     5   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - access("L"."EMP_ID"=:B1)
       2 - access("L"."EMP_ID"=:B1)
    Statistics
              1  recursive calls
              0  db block gets
          22111  consistent gets
             19  physical reads
              0  redo size
         364053  bytes sent via SQL*Net to client
           7672  bytes received via SQL*Net from client
            668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processedThe query improved by a more than a factor of 10 with the index but the consistent gets are still significantly higher then the OUTER JOIN query. Additionally I always try and take the approach when developing queries to minimize the number of table accesses possible. In your second place you have to access the LEAVE table twice, instead of once in the first query.

  • Diff "full outer join" va. "(+)" SELECT syntax ?

    As far as I know there are two ways of defining an outer join:
    Select ... from tab1 t1 full outer join tab2 t2 on t1.id =t2.id;
    or:
    Select ... from tab1 t1, tab2 t2 where t1.id = t2.id(+)
    Are they absolutely equivialent?
    Which are the most common one?
    Which are used on other databases (DB2, MySQL) as well?
    Can I put an additional WHERE clause at the end in the first statement:
    Select ... from tab1 t1 full outer join tab2 t2 on t1.id =t2.id WHERE .....;

    Select ... from tab1 t1 full outer join tab2 t2 on t1.id =t2.id;This is FULL OUTER JOIN
    Select ... from tab1 t1, tab2 t2 where t1.id = t2.id(+)This is LEFT OUTER JOIN.
    They are entirely different.
    FULL OUTER JOIN - Gets all the rows from tab1 and tab2
    LEFT OUTER JOIN - Gets all the rows from tab1 and only the row that matches with join condition from tab2.
    Here is a simple test.
    create table tab1(id integer)
    create table tab2(id integer)
    begin
      insert into tab1 values(1);
      insert into tab1 values(2);
      insert into tab1 values(3);
    end;
    begin
      insert into tab2 values(3);
      insert into tab2 values(4);
      insert into tab2 values(5);
    end;
    Select t1.id, t2.id
      from tab1 t1 full outer join tab2 t2
        on t1.id =t2.id
    Select t1.id, t2.id
      from tab1 t1, tab2 t2
    where t1.id = t2.id(+)
    /Run it and see the result.

  • Inner Selects vs. Outer Joins

    We have a report where we are joining many tables (25 tables) together. Initially, we created the report with outer joins and noticed that the cost of the explain plan was 2600 and the performance was adequate. We then started to remove the outer joins and replacing with inner selects and the cost and performance of the report improved. Currently, we have replaced 13 of the outer joins with inner selects and the cost is down to 650.
    Typically, I have always used joins or outer joins because I thought this was best practice. However, I am now questioning this.
    Is it better to use inner selects when you are only returning one column from a table?
    Other than tables that require multiple columns to be returned, are there issues we should be concerned with?
    Below are examples:
    Thanks,
    Brian
    -- Using Outer Joins
    Select q.quote_id, q.quote_name, l.location_name, sr.sales_rep_name
    from quote q, location l, sales_rep sr
    where q.location_id = l.loation_id (+)
    and q.sales_rep_id = sr.sales_rep_id (+)
    -- Using Inner Selects
    Select q.quote_id, q.quote_name,
    (select location_name from location where location_id = q.location_id) location_name,
    (select sales_rep_name from sales_rep where sales_rep_id = q.sales_rep_id) sales_rep_name
    from quote q

    The cost of a query does not mean better performance. The scalar subqueries that you use when rewriting that query show up in your explain plan with no cost at all, and this is just no true. (a query must "cost" something, right?)
    Instead of starting to rewrite your queries using scalara subqueries, it's better to investigate why a query performs bad.
    If using scalar subquery would always yield a better performance, Oracle would probably rewrite all outer join queries to using scalar subquery.

  • Create a view that limits a large table, but also allows an outer join ?

    oracle 10.2.0.4
    CREATE TABLE MY_PAY_ITEMS
    ( EMP     VARCHAR2(8) NOT NULL
    , PAY_PRD VARCHAR2(8) NOT NULL
    , KEY1    VARCHAR2(8) NOT NULL
    , KEY2    VARCHAR2(8) NOT NULL
    , LN_ITEM VARCHAR2(4) NOT NULL
    , ITEM_AMT NUMBER(24,2) NOT NULL
    , FILLER  VARCHAR2(100) NOT NULL)
    INSERT INTO MY_PAY_ITEMS
    SELECT A.EMP
    , B.PAY_PRD
    , C.KEY1
    , D.KEY2
    , E.LN_ITEM 
    , F.ITEM_AMT
    FROM (SELECT TO_CHAR(ROWNUM, '00000000') "EMP" FROM DUAL  CONNECT BY LEVEL <= 50 ) A
    , (SELECT '2010-' || TO_CHAR(ROWNUM,'00') "PAY_PRD" FROM DUAL CONNECT BY LEVEL <= 52) B
    , (SELECT TO_CHAR(ROWNUM, '000') "KEY1" FROM DUAL CONNECT BY LEVEL <= 8) C
    , (SELECT TO_CHAR(ROWNUM, '000') "KEY2" FROM DUAL CONNECT BY LEVEL <= 5) D
    , (SELECT TO_CHAR(ROWNUM,'000') "LN_ITEM" FROM DUAL CONNECT BY LEVEL <= 20) E
    , (select round(DBMS_RANDOM.VALUE * 400,2)  "ITEM_AMT" from dual) F
    CREATE UNIQUE INDEX MY_PAY_ITEMS ON MY_PAY_ITEMS (EMP, PAY_PRD, KEY1, KEY2, LN_ITEM)
    CREATE TABLE MY_ITEM_DISPLAY
    ( DISPLAY_CODE VARCHAR2(4) NOT NULL
    , SEQUENCE     NUMBER(2) NOT NULL
    , COLUMN_ITEM1 VARCHAR2(4) not null
    , COLUMN_ITEM2 VARCHAR2(4) not null
    , COLUMN_ITEM3 VARCHAR2(4) not null
    , COLUMN_ITEM4 VARCHAR2(4) not null)
    INSERT INTO MY_ITEM_DISPLAY VALUES ('01',10,'001','003','004','005');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('01',20,'007','013','004','009');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('01',30,'001','004','009','011');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('01',40,'801','304','209','111');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('02',10,'001','003','004','005');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('02',20,'007','013','004','009');
    INSERT INTO MY_ITEM_DISPLAY VALUES ('02',30,'001','004','009','011');
    MY_PAY_ITEMS is a table that stores payslip line items.  It has a total size of 500,000,000 rows.
    EMP is the unique employee id,  We have approx 200,000 employees (with approx 50,000 being active today).
    PAY_PRD is a weekly pointer (2010-01, 2010-02 ... 2010-52), we have data from 2004 and are adding a new pay period every week.  2010-01 is defined as the first monday in 2010 to the first sunday in 2010 etc.
    KEY1 is an internal key, it tracks the timeline within the pay period.
    KEY2 is a child of KEY1, it tracks the sequence of events within KEY1.
    LN_ITEM is the actual pay item that resulted from the event on average a person generates 20 rows per event.  Note that in this example everybody gets the same LN_ITEM values, but in practice it is 20 selected from 300
    ITEM_AMT is the net pay for the line item.
    FILLER is an assortment of fields that are irrelevant to this question, but do act as a drag on any row loads.
    MY_ITEM_DISPLAY is a table that describes how certain screens should display items.  The screen itself is a 4 column grid, with the contents of the individual cells being defined as a lookup of LN_ITEMS to retrieve the relevant LN_AMT.
    We have an application that receives a DISPLAY_CODE and an EMP.  It automatically creates a sql statement along the lines of
    SELECT * FROM MY_VIEW WHERE DISPLAY_CODE = :1 AND EMP = :2
    and renders the output for the user.
    My challenge is that I need to rewrite MY_VIEW as follows:
    1) Select the relevant rows from MY_ITEM_DISPLAY where DISPLAY_CODE = :1
    2) Select the relevant all rows from MY_PAY_ITEMS that satisfy the criteria
       a) EMP = :2
       b) PAY_PRD = (most recent one for EMP as at sysdate, thus if they last got paid in 2010-04 , return 2010-04)
       c) KEY1 = (highest key1 within EMP and PAY_PRD)
       d) KEY2 = (highest key2 within EMP, PAY_PRD and KEY1)
    3) I then need to cross reference these to create a tabular output
    4) Finally I have to return a line of 0's where no LN_ITEMs exist ( DISPLAY_CODE 01, sequence 40 contains impossible values for this scenario)
    The below query does part of it (but not the PAY_PRD, KEY1, KEy2 )
    select * from (
    SELECT A.DISPLAY_CODE
    , B.EMP
    , A.SEQUENCE
    , MAX(DECODE(B.LN_ITEM, A.COLUMN_ITEM1, B.ITEM_AMT, 0)) "COL1"
    , MAX(DECODE(B.LN_ITEM, A.COLUMN_ITEM2, B.ITEM_AMT, 0)) "COL2"
    , MAX(DECODE(B.LN_ITEM, A.COLUMN_ITEM3, B.ITEM_AMT, 0)) "COL3"
    , MAX(DECODE(B.LN_ITEM, A.COLUMN_ITEM4, B.ITEM_AMT, 0)) "COL4"
    FROM MY_ITEM_DISPLAY A, MY_PAY_ITEMS B
    WHERE B.PAY_PRD = '2010-03'
    GROUP BY A.DISPLAY_CODE, B.EMP, A.SEQUENCE)
    WHERE DISPLAY_CODE = '01'
    AND EMP = '0000011'
    ORDER BY SEQUENCE
    My questions
    1) How do I do the PAY_PRD, KEY1, KEY2 constraint, can I use some form of ROW_NUMBER() OVER function ?
    2) How do I handle the fact that none of the 4 column LN_ITEMS may exist  (see sequence 40, none of those line items can exist)...  Ideally the above SQL should return
    01, 0000011, 10, <some number>, <some number>, <some number>, <some number>
    01, 0000011, 20, <some number>, <some number>, <some number>, <some number>
    01, 0000011, 30, <some number>, <some number>, <some number>, <some number>
    01, 0000011, 40, 0            , 0            , 0            , 0           
    I tried a UNION, but his prevented the view from eliminating the bulk of the MY_PAY_ITEMS rows, as it resolve ALL of MY_PAY_ITEMS instead of just retrieving rows for the one EMP passed to the view.  The same seems to be true for any outer joins.

    Hi, if i understood you properly, you need :
    select nvl(q.display_code,lag(q.display_code) over (order by rownum)) display_code,
           nvl(q.emp,lag(q.emp) over (order by rownum)) emp,
           m.s,
           nvl(q.COL1,0) COL1,
           nvl(q.COL2,0) COL2,      
           nvl(q.COL3,0) COL3,
           nvl(q.COL4,0) COL4,
           nvl(PAY_PRD,lag(q.PAY_PRD) over (order by rownum)) PAY_PRD,
           nvl(KEY1,lag(q.KEY1) over (order by rownum)) KEY1,
           nvl(KEY2,lag(q.KEY2) over (order by rownum)) KEY2  
    from(
    select d.display_code,
           t.emp,
           d.sequence,
           max(DECODE(t.LN_ITEM, d.COLUMN_ITEM1, t.ITEM_AMT, 0)) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) "COL1",
           max(DECODE(t.LN_ITEM, d.COLUMN_ITEM2, t.ITEM_AMT, 0)) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) "COL2",
           max(DECODE(t.LN_ITEM, d.COLUMN_ITEM3, t.ITEM_AMT, 0)) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) "COL3",
           max(DECODE(t.LN_ITEM, d.COLUMN_ITEM4, t.ITEM_AMT, 0)) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) "COL4",
           max(t.PAY_PRD) PAY_PRD,
           max(t.key1) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) key1,
           max(t.key2) keep (dense_rank first order by to_date(t.pay_prd,'yyyy-mm') desc ) key2
      from MY_PAY_ITEMS t
      join MY_ITEM_DISPLAY d
        on d.display_code = '01'
    where t.emp = '00000011'
    group by d.display_code, t.emp, d.sequence
    ) q
    full outer join (select level*10 s from dual connect by level <= 4) m
    on m.s = q.sequence
    DISPLAY_CODE
    EMP
    S
    COL1
    COL2
    COL3
    COL4
    PAY_PRD
    KEY1
    KEY2
    01
    00000011
    10
    101.1
    103.1
    104.1
    105.1
    2010-03
    008
    005
    01
    00000011
    20
    107.1
    113.1
    104.1
    109.1
    2010-03
    008
    005
    01
    00000011
    30
    101.1
    104.1
    109.1
    111.1
    2010-03
    008
    005
    01
    00000011
    40
    0
    0
    0
    0
    2010-03
    008
    005
    Ramin Hashimzade

  • OUTER JOIN 의 GUIDE LINE

    제품 : ORACLE SERVER
    작성날짜 : 2002-04-10
    OUTER JOIN 에 대하여
    ====================
    Purpose
    Outer join의 효과과 이용방법에 대해 이해한다.
    Explanation
    1. 개념
    다음의 용어에 대해 우선 살펴보자 :
    1) outer-join column - symbol(+) 을 사용하는 column 이다 .
    예를 들어 EMPNO(+) ,DEPT.DEPTNO(+) 는 outer join column들이다.
    2) simple predicate - AND , OR,NOT 을 가지지 않는 단순한 관계표현으로
    A=B 의 관계로 표현된다.
    3) outer join predicate - 한개 이상의 outer join column 을 갖는 simple
    predicate 이다.
    2. OUTER JOIN 사용법 - RULES
    outer join predicate 는 오직 1 table 의 column 들 만이 outer join
    column 으로 이용되어져야 한다. 즉 한 single outer join predicate 의
    모든 outer join column 은 모두 같은 table이어야 한다.
    이런 취지에서 다음 statement 는 틀린 것이다.
    EMP.EMPNO(+) = DEPT.DEPTNO(+)
    이것은 두 table 의 outer join column 들이다.
    한 predicate 의 한 column 이 outer join column 이면 같은 table 의 모든
    column 은 outer join column 이어야 한다.
    이 취지에서 다음 문장은 틀린 것이다.
    EMP.SAL + EMP.COMM(+) = SALGRADE.HIGH
    한 table 의 column 들이 outer join 것과 아닌 것과 outer join 인것으로
    섞여있기 때문이다.
    predicate 에서 (+) 표시가 붙은 table 은 다른 table 을 direct 하게
    outer join 한다. indirect 하게 다른 tabe 을 outer join 한다는 것은
    그들 table 자체가 또 outer join 하는 경우이다.
    이 경우 한 table 은 direct하게든 indeirect 하게든 자기 자신에게 outer
    join 하는 경우는 허용되지 않는다.
    다음의 문장은 이런 취지에서 틀린 경우이다.
    EMP.EMPNO(+) = PERS.EMPNO
    AND PERS.DEPTNO(+) = DEPT.DEPTNO
    AND DEPT.JOB(+) = EMP.JOB - circular outer
    join relationship
    3. OUTER JOIN 실행
    주어진 table T 에는 outer join 과 non-outer join 이 있다.
    실행시 다음처럼 수행된다.
    1) The result of joining all tables mentioned in table T's
    outer join predicates is formed ( by recursive application
    of this algorithm ).
    2) For each row of the result, a set of composite rows is
    formed, each consisting of the original row in the
    result joined to a row in table T for which the composite
    row satisfies all of table T's outer join predicates.
    3) If a set of composite rows is the null set, a composite
    row is created consisting of the original row in the
    result joined to a row similar to those in table T, but
    with all values set to null.
    4) Rows that do not pass the non-outer join predicates are removed.
    This may be summarised as follows. Outer join
    predicates ( those with (+) after a column of table T ), are
    evaluated BEFORE table T is augmented with a null row. The null
    row is added only if there are NO rows in table T that satisfy
    the outer join predicates. Non-outer join predicates are
    evaluated AFTER table T is augmented with a null row (if needed)
    4. OUTER JOIN - RECOMMENDATIONS
    Certain types of outer joins in complicated logical
    expressions may not be well formed. In general, outer join
    columns in predicates that are branches of an OR should be
    avoided. Inconsistancies between the branches of the OR can
    result in an ambiguous query, and this may not be detected. It
    is best to confine outer join columns to the top level of the
    'where' clause, or to nested AND's only.
    5. OUTER JOIN - ILLUSTRATIVE EXAMPLES
    1) Simple Outer Join
    SELECT ENAME, LOC
    FROM DEPT, EMP
    WHERE DEPT.DEPTNO = EMP.DEPTNO(+)
    The predicate is evaluated BEFORE null augmentation. If
    there is a DEPT row for which there are no EMP rows, then a null
    EMP row is concatenated to the DEPT row.
    2) Outer Join With Simple Post-Join Predicates
    SELECT ENAME, LOC
    FROM DEPT, EMP
    WHERE DEPT.DEPTNO = EMP.DEPTNO(+)
    AND EMP.DEPTNO IS NULL
    The second simple predicate is avaluated AFTER null
    augmentation, since there is no (+), removing rows which were
    not the result of null augmentation and hence leaving only DEPT
    rows for which there was no corresponding EMP row.
    3) Outer Join With Additional Pre-Join Predicates
    SELECT ENAME, LOC
    FROM DEPT, EMP
    WHERE DEPT.DEPTNO = EMP.DEPTNO(+)
    AND 'CLERK' = EMP.JOB(+)
    AND EMP.DEPTNO IS NULL
    The predicate on EMP.JOB is evaluated at the same time
    as the one on EMP.DEPTNO - before null augmentation. As a
    result, a null row is augmented to any DEPT row for which there
    are no corresponding clerks's in the EMP table. Therefore, this
    query displays departments containing no clerks.
    Note that it the (+) were omitted from the EMP.JOB
    predicate, no rows would be returned. In this case, both the
    EMP.JOB and EMP.DEPTNO IS NULL predicates are evaluated AFETR
    the outer join, and there can be no rows for which both are
    true.

    I had to put it in a subquery? (if that's what it's called)
    SELECT a1.date_field DateAndHour, b1.OR_date, NVL(b1.record_count,0)
    FROM  MASTER_DATE_TABLE a1,
                  (SELECT TO_CHAR(b.OR_IN_DTTM,'YYYYMMDDHH24') OR_date, COUNT(*) record_count
                FROM hsa_tgt.PICIS_OR b
                GROUP BY TO_CHAR(b.OR_IN_DTTM,'YYYYMMDDHH24')) b1
    WHERE a1.date_field  = b1.OR_date (+)
    GROUP BY a1.date_field, b1.OR_date, b1.record_count
    HAVING (TO_DATE(a1.date_field,'YYYYMMDDHH24') BETWEEN '01-Jan-2006' AND '31-Jan-2006')
    ORDER BY a1.date_field;

  • 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

  • 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.

  • [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.

  • Error in making left outer join to a nested query

    i am writing this query getting error here i am using nested query with that i am making join it is giving error
    SQL
    SELECT
    * FROM IVItem INNER JOIN
    IVPackSize_Mst ON IVItem.PackSizeID = IVPackSize_Mst.Id
    left outer join IvItemGenericLink on IvItemGenericLink.itemID=IVItem.Id
    Select GenericId from
    IvItemGenericLink where ItemID=IVItem.Id and rownum <=1
    )x
    and x on IvItemGenericLink.GenericId=x.GenericId;
    Error report:
    SQL Error: ORA-00936: missing expression
    00936. 00000 - "missing expression"
    *Cause:   
    *Action:
    give me and suggestion

    i am using left outer join at virtual table say x your gave me its equivalent
    EXISTS (SELECT 1 FROM IvItemGenericLink G
    WHERE G.ITEMID =V.ID
    AND G.GenericId = L.GenericId)-----its i guess inner join
    i am not confirmed that why iam asking this i guess i have to use this
    as i use keyword inner join for inner join and for left join i use
    left outer join
    EXISTS (SELECT 1 FROM IvItemGenericLink G
    WHERE G.ITEMID =V.ID
    AND G.GenericId(+) = L.GenericId)-----its i guess left outer join
    left outer join
    Select GenericId from
    IvItemGenericLink where ItemID=IVItem.Id and rownum <=1
    )*x*
    IvItemGenericLink.GenericId=x.GenericId
    -------------------Statement U Gave in this--------------------------------------------------------------------------
    SELECT *
    FROM IVITEM V, IVPACKSIZE_MST M , IVITEMGENERICLINK L,
    WHERE V.PACKSIZEID = M.ID
    AND V.ID = L.ITEMID (+)
    AND EXISTS (SELECT 1 FROM IvItemGenericLink G
    WHERE G.ITEMID =V.ID
    AND G.GenericId = L.GenericId)
    -------------------Statement U Gave in this--------------------------------------------------------------------------
    is this equivalent to left outer join
    *AND EXISTS (
    SELECT 1 FROM IvItemGenericLink G*
    WHERE G.ITEMID =V.ID
    *AND G.GenericId = L.GenericId
    please tell me this in this regard

  • Help to rewrite left outer join

    I have the query below running on Db2 AND SQL SERVER 2005 with the syntax as shown. I cannot find a way to make Oracle work with this syntax.
    Can you, please help me do this?
    I need to keep all database statements the same for all databases and in this case I cannot implement this one.
    Regular statement that I do not want to use anymore because executes additional filters:
    SELECT
    s.conflict_id as source_id,
    s.disp_comments --some more fields going here
    FROM sep_conflict s
    left outer join app_activity_history h hist
    on s.conflict_id = hist.source_idNew syntax for SQL server and db2 that I need analog for Oracle:
    SELECT
    s.conflict_id as source_id,
    s.disp_comments --some more fields going here
    FROM sep_conflict s
    left outer join (select source_id from app_activity_history h )as hist (source_id)
    on s.conflict_id = hist.source_idThanks a lot for the help, mj

    Your second query looks similar to this;
    SQL> with sep_conflict as (
       select 1 conflict_id, 1 disp_comments from dual union all
       select 2 conflict_id, 2 disp_comments from dual),
         app_activity_history as (
       select 1 source_id from dual union all
       select null source_id from dual)
    /* End of test data */
    SELECT
       s.conflict_id source_id, s.disp_comments, hist.source_id
    FROM sep_conflict s
    left outer join (select source_id
         from app_activity_history) hist
    on s.conflict_id = hist.source_id
    SOURCE_ID DISP_COMMENTS  SOURCE_ID
             1             1          1
             2             2          
    2 rows selected.

Maybe you are looking for

  • How to connect to HD TV after upgrade to OS 10.8.2

    How can I connect to my Sony HD TV after upgrade to OS 10.8.2? It worked before I upgraded and now it doesn't recognize the TV in the Display Pref.

  • Itunes crashed, lost files??, files wont play.

    i just tried itunes for the first time, i am running windows vista and if i had bean aware of the problems between itunes and vista i probably would not have done this. anways my problem. when i first installed itunes it ran good and i setup an accou

  • HP SPLIT 13 X 2 PC

    i bought it refurbished and through support found the secondary being the keyboard battery is bad. the keyboard is a sealed type and my question is can the factory replace the battery or will they just switch out and how will i know. im concerned tha

  • Back button in AS3

    I did a search on this and didn't find a successful answer yet. I need to have a back button in AS3 that'll remember the last frame visited from any frame in the site. There are various buttons to get to various frames, and the one back button will a

  • How and where will we create " hierarchy "variables?-urgent

    hi, how to create hierarchy variables? where they will be seen while creating a query? plz tell in detail.. Message was edited by:         neeraja devi