Cross-listing Query (Partition By Clause? Self-Join?)

Hello,
I need a query that will cross-list courses a professor is teaching this semester. Essentially, two fields need to be the same (i.e.: Section & CourseTitle), while the third field is different (i.e.: Subject).
For example, Max Power is a professor teaching 3 courses, one is cross-listed (ENG 123 and JRL 123):
LastName     FirstName     Subject     Section     CourseTitle
Power          Max          ENG     123     English Composition
Power          Max          ENG     452     Robert Frost Poetry     
Power          Max          JRL     123     English Composition
Power           Max          ENG      300     Faulkner & TwainThe desired query output is this:
LastName     FirstName     Subject     Section     CourseTitle
Power          Max          ENG     123     English Composition
Power          Max          JRL     123     English CompositionBasically, I need only the cross-listed courses in the output.Is this an instance where I use a "Partition By Clause" or should I create a self-join?
Much thanks for any help and comments.

Unfortunately, I can't create new tables. I don't have permission. I can't alter, add or delete any of the data.
So I tried Frank's code with my data:
WITH got_cnt AS
SELECT  sivasgn_term_code, spriden_id, spriden_last_name, spriden_first_name,
                ssbsect_ptrm_code, ssbsect_camp_code,
                sivasgn_crn, ssbsect_subj_code, ssbsect_crse_numb, scbcrse_title,
       count(*) over (partition by ssbsect_crse_numb, scbcrse_title) cnt
FROM spriden INNER JOIN sivasgn ON spriden_pidm = sivasgn_pidm JOIN
     ssvsect ON ssbsect_crn = sivasgn_crn JOIN
     sfrstcr ON sfrstcr_crn = sivasgn_crn
WHERE  ssbsect_term_code= sivasgn_term_code  
AND sfrstcr_term_code = sivasgn_term_code
AND ssbsect_enrl > '0' and sivasgn_credit_hr_sess > '0'
AND sivasgn_term_code IN ('200901', '200909')
AND spriden_change_ind IS NULL
AND ssbsect_camp_code IN ('1', '2', 'A', 'B')
SELECT DISTINCT sivasgn_term_code, spriden_id, spriden_last_name, spriden_first_name,
                substr(ssbsect_ptrm_code,1,1) as ptrm_code, ssbsect_camp_code,
                sivasgn_crn, ssbsect_subj_code, ssbsect_crse_numb, scbcrse_title
FROM got_cnt
WHERE cnt >1
ORDER BY spriden_last_name, sivasgn_term_code, ssbsect_crse_numb;The output pretty much displays all courses with same subject code, course number and course title.
Output:
LastName     FirstName     Subject     Section     CourseTitle
Power          Max          ENG     123     English Composition
Power          Max          ENG     123     English Composition
Power          Max          ENG     452     Robert Frost Poetry
Power          Max          ENG     452     Robert Frost Poetry
Power           Max          ENG      300     Faulkner & Twain
Power           Max          ENG      300     Faulkner & Twain
Power          Max          JRL     123     English Composition
Power          Max          JRL     123     English CompositionWhat I would like is same course number, course title, BUT different subject code. Pretty much that in my first post of this thread.
Desired Output:
LastName     FirstName     Subject     Section     CourseTitle
Power          Max          ENG     123     English Composition
Power          Max          JRL     123     English CompositionMaybe I'm explaining this wrong. Any help would be greatly appreciated. Thanks.

Similar Messages

  • Oracle query with out using self join

    hi friends,
    i have one table for exeample PERSTATUS
    pk/fK STUDENT NUMBER SUBJECT MARKS STATUS
    1 ACCOUNTS 15 RED
    1 MATHS 35 YELLOW
    1 SCINECE 45 GREEN
    2 ACCOUNTS 55 BROWN
    2 MATHS 35 YELLOW
    2 SCINECE 45 GREEN
    3 ACCOUNTS 15 RED
    3 MATHS 35 YELLOW
    3 SCINECE 45 GREEN
    i want students how status is both red and yellow so i am using self join
    i want students status is both red and yellow so i am using self join
    SELECT PS.STUDENTNUMBER,PS.STATUS,PS.STATUS1 FROM PERSTATUS PS ,PERSTATUS PS1
    WHERE PS.STUDENTNUMBER-PS1.STUDENTNUMER
    PS.STATUS='RED' AND PS1.STAUTS='YELLOW'
    i want students status is both RD and YELLOW AND GREEN so i am using self join( two self joinS}
    SELECT PS.STUDENTNUMBER,PS.STATUS,PS.STATUS,PS2.STATUS FROM PERSTATUS PS ,PERSTATUS PS1,PERSTATUS PS2
    WHERE PS.STUDENTNUMBER-PS1.STUDENTNUMER AND PS.STUDENTNUMBER-PS2.STUDENTNUMBER
    PS.STATUS='RED' AND PS1.STAUTS='YELLOW' AND PS2.STAUTUS='GREEN'
    if i require MORE STATUS then more self joins required, is there any alternative to achive this
    and if results comes in multiple rows are accepted (since with the above query result will come in single row)
    i tried to use group by (studentnumber,status) with status='red' and status='yellow'
    but it is not possible could you povidet he solution

    Hi,
    Whenever you have a problem, please post CREATE TABLE and INSERT statements for your sample data, and the exact results you want from that data. Explain how you get those results from that data.
    See the forum FAQ {message:id=9360002}
    Here's an example of how to post the sample data:
    CREATE TABLE     perstatus
    (       studentnumber     NUMBER
    ,     subject          VARCHAR2 (10)
    ,     marks          NUMBER
    ,     status          VARCHAR2 (10)
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (1,           'ACCOUNTS', 15,       'RED');
    INSERT INTO perstatus (studentnumber, subject  ,  marks, status)
           VALUES           (1,           'MATHS',        35,       'YELLOW');
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (1,           'SCINECE',  45,       'GREEN');
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (2,           'ACCOUNTS', 55,       'BROWN');
    INSERT INTO perstatus (studentnumber, subject  ,  marks, status)
           VALUES           (2,           'MATHS',        35,       'YELLOW');
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (2,           'SCINECE',  45,       'GREEN');
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (3,           'ACCOUNTS', 15,       'RED');
    INSERT INTO perstatus (studentnumber, subject  ,  marks, status)
           VALUES           (3,           'MATHS',        35,       'YELLOW');
    INSERT INTO perstatus (studentnumber, subject,    marks, status)
           VALUES           (3,           'SCINECE',  45,       'GREEN');You were on the right track, thinking about GROUP BY. You're interested in something about the whole group of rows that has the same studentnumber. Looking at any individual row won't tell you if that row is part of the group you're interested in or not.
    If you want to see information about the group as a whole, you can do the whole job with GROUP BY. In this case, studnetnumber is the only thing that an entire group has in common. If you wanted to see the studentnumbers that had both RED and YELLOW, that is:
    STUDENTNUMBER
                1
                3here's one way you could do it:
    SELECT       studentnumber
    FROM       perstatus
    WHERE       status     IN ('RED', 'YELLOW')
    GROUP BY  studentnumber
    HAVING       COUNT (DISTINCT status) = 2  -- That is, both RED and YELLOW
    ORDER BY  studentnumber
    ;But say you wanted to see details about individuals in the group; for example, say we want to see all the columns for students that have all 3 of RED, YELLOW and GREEN, like this:
    STUDENTNUMBER SUBJECT         MARKS STATUS
                1 SCINECE            45 GREEN
                1 ACCOUNTS           15 RED
                1 MATHS              35 YELLOW
                3 SCINECE            45 GREEN
                3 ACCOUNTS           15 RED
                3 MATHS              35 YELLOWWe used the aggregate COUNT function earlier, but aggregate functions require collapsing the results down to one row per group.
    However, most of the aggregate functions, like COUNT, have analytic counterparts, that can give the same results without collapsing the result set. Here's one way to get the results above, using the analytic COUNT function:
    WITH     got_cnt          AS
         SELECT  studentnumber, subject, marks, status
         ,     COUNT ( DISTINCT CASE
                                   WHEN  status  IN ('RED', 'YELLOW', 'GREEN')
                             THEN  status
                               END
                    ) OVER (PARTITION BY  studentnumber)     AS cnt
         FROM    perstatus
    SELECT    studentnumber, subject, marks, status
    FROM       got_cnt
    WHERE       cnt  = 3
    ORDER BY  studentnumber
    ,            status
    ;

  • Query on Recursive Table (self-join)?

    Hi all,
    I have a table with a self join, basically an employee is managed by an employee..
    Using the following query, i'm able to query the data, giving a kind of hierarchical output, this tells me who manages who...
    SELECT LPAD(' ', 5* level) || empno
    FROM employee
    CONNECT BY prior empno = mgr
    START WITH mgr is null;This produces the following output...
    SQL> SELECT LPAD(' ', 5* level) || ep_emp_id
      2  FROM employee_on_project
      3  CONNECT BY prior ep_emp_id = ep_mgr_emp_id
      4  START WITH ep_mgr_emp_id is null;
    LPAD('',5*LEVEL)||EP_EMP_ID
         c1
              c2
                   c4
                   c5
                   c6
              c3
         c7
    7 rows selected.My question is, how can I edit the query to output only employees at the top of the hierarchy, i.e. only top managers.
    Any idea's guys??
    Cheers!

    Depending on what you mean by "top managers", but this seems the obvious solution:
    SELECT ep_emp_id
    FROM employees_on_project
    WHERE ep_mgr_emp_id IS NULLalternatively, if employees_on_project is actually complex view, and not a simple table, then this may be a better alternative:
    SELECT emp_id
    FROM (SELECT ep_emp_id, level lv
          FROM employee_on_project
          CONNECT BY prior ep_emp_id = ep_mgr_emp_id
          START WITH ep_mgr_emp_id is null)
    WHERE lv = 1TTFN
    John

  • SQL Query, group by or self join?

    Hi All,
    I have a table with about 100,000 rows.. It is a linking table. I want to filter out some of the data. At the bottom I will put a sample table. I am really after advice if I should be using the group by, or something else. It is really slow, and I really wanted to make a view from the query, but it won't run in realtime (I thought about Materialised views, but the data could change and I would want it updated)
    So the data would like like this.
    1 1
    A 1
    B 1
    1 A
    1 B
    2 null/0
    And I want to transform it into a result that looks like this.
    A 1
    B 1
    2 0
    (I can live with 1 1 as well)
    The first query I have come up with is
    select
    A.TXN, A.ID SCHED_INFO, A.STA ORIG_ACT
    from
    SELECT
    Txn, ID,
    STA
    FROM TEST_STA
    WHERE TXN < 0
    ) A,
    select ID, count(STA)
    FROM test_STA
    WHERE TXN < 0
    group by ID
    HAVING count(STA) > 1
    ) B
    where A.ID = B.ID
    OR A.STA = '0'
    The second I came up with was.
    select B.Id , A.id STA
    from test_STA A, test_STA B
    where A.STA = '0'
    AND B.STA != '0'
    AND B.STA = A.ID
    AND b.TXN < 0
    Where the data looks like
    create table test_STA
    ( TXN NUMBER,
    ID VARCHAR2(20),
    STA VARCHAR2(20) )
    insert into test_STA Values (1, '1', '0')
    insert into test_STA Values (-1, '1', '1')
    insert into test_STA Values (-1, '1', 'A')
    insert into test_STA Values (-1, '1', 'B')
    insert into test_STA Values (-1, 'A', '1')
    insert into test_STA Values (-1, 'B', '1')
    insert into test_STA Values (-1, '2', '0')
    TXN is the transaction number -1 is current, others (> 0 are old)
    What does all this mean..
    Well
    1 is a parent, with A and B as children.
    2 is a parent with no children.
    So what I want to do return is Parents with no children, and children but not their parents..
    So which path should I continue my efforts down do you think ? The first one, with the group by, or the second one, with the join to it's self.
    Paul

    Hi,
    If you can guarantee, that every child has also a record then following query returns your result:
    select ID, count(*)
    from test_STA
    group by ID
    having count(*) = 1
    ID COUNT(*)
    2     1
    A     1
    B     1

  • Self-join query to Analytical function query

    Hi All,
    I have converted a self-join query to Analytical function query due to the performance reasons.
    Query which is using Analytical function is giving the correct count as I compared it with query using Self-Join. Can you please tell what is wrong in the query.
    ==========================
    Query using Self-Join
    select count(1)
    From (select t1.*, max(t1.dw_creation_dt) over (partition by t1.empl_id) pers_max_date
    from ohr_pers_curr t1 ) pers
         , (select t2.*, max(t2.dw_creation_dt) over (partition by t2.empl_id, t2.empl_rcd) job_max_date
         from OHR_JOB_CURR t2) job
    where pers.empl_id = job.empl_id
    and pers.dw_creation_dt=pers.pers_max_date
    and job.dw_creation_dt=job.job_max_date
    and job.dummy_row_flag = 'N'
    and pers.dw_creation_rsn_cd in ('N', 'U')
    and job.dw_creation_rsn_cd in ('N', 'U')
    ================================================
    Query Using Analytical function
    select count(1)
    From (select t1.*, max(t1.dw_creation_dt) over (partition by t1.empl_id) pers_max_date
    from ohr_pers_curr t1 ) pers
         , (select t2.*, max(t2.dw_creation_dt) over (partition by t2.empl_id, t2.empl_rcd) job_max_date
         from OHR_JOB_CURR t2) job
    where pers.empl_id = job.empl_id
    and pers.dw_creation_dt=pers.pers_max_date
    and job.dw_creation_dt=job.job_max_date
    and job.dummy_row_flag = 'N'
    and pers.dw_creation_rsn_cd in ('N', 'U')
    and job.dw_creation_rsn_cd in ('N', 'U')
    ==================================

    Hi David,
    The base is same but the problem is different.
    As far as implementation concern these queries looks same, but when I see there counts, they do not match. I do not have any reason why this happening.
    Regards
    Gaurav

  • Outer join on query with OR clause

    hi all, i am having problem outerjoining a query with or clause
    here is my data
    WITH table1 AS
    SELECT  'test' txt1, 'pak' txt2, 'ced' txt3, 'su' txt4 FROM dual UNION ALL
    SELECT  null txt1, 'pak' txt2, 'ced2' txt3, 'su2' txt4 FROM dual UNION ALL
    SELECT  null txt1, NULL txt2, 'ced3' txt3, 'su3' txt4 FROM dual UNION ALL
    SELECT  null txt1, NULL txt2, null txt3, 'su3' txt4 FROM dual UNION ALL
    SELECT  'text5' txt1, NULL txt2, null txt3, 'su3' txt4 FROM dual UNION ALL
    SELECT  null txt1, NULL txt2, null txt3, null txt4 FROM dual
    ,table2 AS
    SELECT 111 pid, 'test' txt1, 'pak4' txt2, 'ced' txt3, 'su' txt4 FROM dual UNION ALL
    SELECT 222 pid, 'test1' txt1, 'pak' txt2, 'ced2' txt3, 'su2' txt4 FROM dual UNION ALL
    SELECT 333 pid, 'test2' txt1, 'pak3' txt2, 'ced3' txt3, 'su4' txt4 FROM dual UNION ALL
      SELECT 444 pid, 'test2' txt1, 'pak3' txt2, 'ced4' txt3, 'su3' txt4 FROM dual
    SELECT b.pid, a.*
    from table1 a, table2 b
    WHERE (a.txt1 = b.txt1 OR
           a.txt1 IS NULL AND a.txt2=b.txt2 OR
           Nvl(a.txt2, a.txt1) IS NULL AND a.txt3 = b.txt3 OR
           Nvl(a.txt2, a.txt1) IS NULL  AND a.txt3 IS NULL AND a.txt4 = b.txt4
           ) as you can see i am joining table1 and table 2. i am joining with txt1, if txt1 is null then join by txt2, if null then join by txt3 and so on.
    the code above product this output
    PID     TXT1     TXT2     TXT3     TXT4
    ===     ====     ===   ==== ====
    111     test     pak      ced     su
    222             pak      ced2     su2
    333                     ced3     su3
    444                          su3this output is partially correct. only 4 rows were display and two was left out
    SELECT  'text5' txt1, NULL txt2, null txt3, 'su3' txt4 FROM dual UNION ALL
    SELECT  null txt1, NULL txt2, null txt3, null txt4 FROM dual i tried using outer join but oracle complain that i cannot use outerjoin with OR clause.
    can someone help modify my query to display the output below ?
    PID     TXT1     TXT2     TXT3     TXT4
    ===    ====      ===   ====  ====
    111     test     pak      ced     su
    222             pak      ced2     su2
    333                     ced3     su3
    444                          su3
    NULL  NULL   NULL    NULL   NULL
         test5

    Not sure you can do it with the Oracle style outer joins, but wioth ANSI style joins it is simple, actually exactly as you had it.
    SQL> set null null;
    SQL> WITH table1 AS (
      2   SELECT  'test' txt1, 'pak' txt2, 'ced' txt3, 'su' txt4 FROM dual UNION ALL
      3   SELECT  null txt1, 'pak' txt2, 'ced2' txt3, 'su2' txt4 FROM dual UNION ALL
      4   SELECT  null txt1, NULL txt2, 'ced3' txt3, 'su3' txt4 FROM dual UNION ALL
      5   SELECT  null txt1, NULL txt2, null txt3, 'su3' txt4 FROM dual UNION ALL
      6   SELECT  'text5' txt1, NULL txt2, null txt3, 'su3' txt4 FROM dual UNION ALL
      7   SELECT  null txt1, NULL txt2, null txt3, null txt4 FROM dual),
      8  table2 AS (
      9   SELECT 111 pid, 'test' txt1, 'pak4' txt2, 'ced' txt3, 'su' txt4 FROM dual UNION ALL
    10   SELECT 222 pid, 'test1' txt1, 'pak' txt2, 'ced2' txt3, 'su2' txt4 FROM dual UNION ALL
    11   SELECT 333 pid, 'test2' txt1, 'pak3' txt2, 'ced3' txt3, 'su4' txt4 FROM dual UNION ALL
    12   SELECT 444 pid, 'test2' txt1, 'pak3' txt2, 'ced4' txt3, 'su3' txt4 FROM dual)
    13  SELECT b.pid, a.*
    14  from table1 a
    15     LEFT JOIN table2 b
    16        ON (a.txt1 = b.txt1 OR
    17            a.txt1 IS NULL AND a.txt2=b.txt2 OR
    18            Nvl(a.txt2, a.txt1) IS NULL AND a.txt3 = b.txt3 OR
    19            Nvl(a.txt2, a.txt1) IS NULL  AND a.txt3 IS NULL AND a.txt4 = b.txt4);
           PID TXT1   TXT2   TXT3   TXT4
           111 test   pak    ced    su
           222 null   pak    ced2   su2
           333 null   null   ced3   su3
           444 null   null   null   su3
    null       text5  null   null   su3
    null       null   null   null   nullJohn

  • Need help with self join query

    Hello,
    I have table A with the following data
    oid parent_oid
    10 4
    4 2
    2 2
    12 6
    6 6
    parent_oid is the parent of oid. I'd like a query that shows the final parent of the oid. The result should show the following
    oid final parent
    10 2
    4 2
    2 2
    12 6
    6 6
    I'm using Oracle 10g. I'm familiar with self joins, but that alone will not do the job. Thanks!

    Hi,
    arizona9952 wrote:
    ... I'm familiar with self joins, but that alone will not do the job.You're absolutely right!
    A 2-way self join would work for rows have no parent, or rows that are directly connected to their final ancestor (such as oid=4), but not for anything farther away.
    A 3-way self-join would work for one more level away from the final row, but no more. That would be enough for the small set of sample data that you posted, but it would not work if you added a new row with parent_id=10.
    An N-way self-join would work for up to N+1 levels, but no more.
    You need something that can go any number of levels, such as CONNECT BY:
    SELECT     CONNECT_BY_ROOT oid     AS oid
    ,     parent_oid          AS final_parent
    FROM     a
    WHERE     CONNECT_BY_ISLEAF     = 1
    CONNECT BY     oid     = PRIOR parent_oid
         AND     oid     != parent_oid
    ;Edited by: Frank Kulash on Feb 22, 2010 7:09 PM
    Upon sober reflection, I think that a Top-Down query, like the one below, would be more efficient than a Bottom-Up query, like the one above:
    SELECT     oid
    ,     CONNECT_BY_ROOT     parent_oid     AS final_parent
    FROM     a
    START WITH     parent_oid     = oid
    CONNECT BY     parent_oid     = PRIOR oid
         AND     oid          != PRIOR oid
    ;

  • Self join using ABAP Query

    Hello all,
    How to create a self join using ABAP Query?
    Say, I have this table EKBE with belnr (materials doc num) and lfbnr (reference material doc num). I have to pick the PO's from EKBE whose belnr doesnt have any lfbnr.
    Regards
    Madhumathi A

    hi madhu,
    tables : ekbe.
    data itab like standard table of ekbe with header line.
    select * from ekbe into table itab where belnr >< 0 and lfbnr = ' '.
    loop at itab.
    write :/ itab-belnr,itab-lfbnr.
    endloop.
    check this code this works to select the orders whose belnr doesnt have any lfbnr
    reward points if useful.

  • Self Joining and Inline Query. A tricky report.

    I am stuck with a very tricky situation.Please help.This is PROD issue.
    I have written a SQL code which has 1 inline queries,and displays the right results
    with the right report output
    Dont get confused.Just go thru this.
    select   pie.id_inst_code,
             ISNULL(PN.Active, 0)                 'Active',
    from position_master_input_event pie,
    (select  insx.id_inst_xref_type,insx.id_inst_xref,count(*) 'PrimaryListing'
    from instrument ins, instrument_xref insx
    where ins.id_inst = insx.id_inst
    and   insx.flg_active = 'Y'
    and   ins.flg_active  = 'Y'
    group by insx.id_inst_xref_type,insx.id_inst_xref
    )PN
    where     id_entity = 'AGL'
    and       pie.id_inst_code *= PN.id_inst_xref
    and       pie.id_src_inst_code_type*= PN.id_inst_xref_type
    group by  pie.id_inst_code,PN.Active,
    Table :Instrument_xref
    id_inst      id_inst_xref_type    id_inst_xref  flg_active
    0372285      SE                   B0DV8Y9       Y
    0372285      IS                   GB00B03MLX29  Y
    Table :Instrument
    id_inst      id_inst_xref_type    id_inst_xref  flg_active  flg_primary_listing
    0372285      SE                   B0DV8Y9       Y           N 
    OUTPUT:
    id_inst_xref                      Active
    B0DV8Y9                           1
    PERFECT.Works fine
    2) Now comes the tricky part.:
        0372285 also has GB00B03MLX29 which has flg_active to Y and which also maps to 0372285.
        Am I right?
        New reportOutput
        id_inst_xref                      Active   PRIMARY ISIN
        B0DV8Y9                           1        1
        So,now I want a SELF JOIN this way built into the code:
        (hardcoded values work)
        (i)
        select  a.id_inst_xref
        from instrument_xref a,
             instrument_xref b
        where b.id_inst_xref ='B0DV8Y9'
        and   b.id_inst = a.id_inst
        and   b.id_inst_xref_type in ('SE','IS')
        and   a.id_inst_xref =  'GB00B03MLX29'
        (ii)
         select count(*) 'PrimaryISIN'
         from instrument ins,
             instrument_xref insx
         where ins.id_inst = insx.id_inst
         and   insx.flg_active = 'Y'
         and   ins.flg_primary_listing = 'Y'
         and   ins.flg_active = 'Y'
         And now LINKING ALL :
        select   pie.id_inst_code,
             ISNULL(PN.Active, 0)                 'Active',
        from position_master_input_event pie,
        (select  insx.id_inst_xref_type,insx.id_inst_xref,count(*) 'PrimaryListing'
         from instrument ins, instrument_xref insx
         where ins.id_inst = insx.id_inst
         and   insx.flg_active = 'Y'
         and   ins.flg_active  = 'Y'
         group by insx.id_inst_xref_type,insx.id_inst_xref
        )PN,
        (select count(*) 'PrimaryISIN'
         from instrument ins,
             instrument_xref insx
         where ins.id_inst = insx.id_inst
         and   insx.flg_active = 'Y'
         and   ins.flg_primary_listing = 'Y'
         and   ins.flg_active = 'Y'
          and     insx.id_inst_xref = ( 
                                           select  DISTINCT  a.id_inst_xref
                                            from    instrument_xref a,
                                            instrument_xref  b
                                      where b.id_inst_xref = 'B0DV8Y9'
                                          and     b.id_inst = a.id_inst
                                          and     b.id_inst_xref_type in ('SE','IS')
                                       and    a.id_inst_xref =  'GB00B03MLX29'
        where     id_entity = 'AGL'
        and       pie.id_inst_code *= PN.id_inst_xref
        and       pie.id_src_inst_code_type*= PN.id_inst_xref_type
        group by  pie.id_inst_code,PN.Active,
        THE Self join works fine as long as it is hardcoded.
        But assume there can br multiple such situations as the above,and I dont want to
        hardcode the values,how can I build the NEW REPORT by SELF JOINING.
        Please can someome help.This is a tricky one.
        Is there a better way to this

    Isn't this the same question as:
    Passing values dynamically Froman 'INLINE Query' to a 'SUB QUERY'
    and
    Another query regarding Inline Query and Self Join and pass Column Values

  • How to tune self join query in Oracle 11g

    Oracle & SQL new to me,and I'm still in learning phase.
    Could you please help me to tune below oracle query?? This table contains ~95 lac records and it takes 1 hour to retrieve data using this query.
    Your suggestions/comments/help will be appreciated.
    Thanks in advance.
    SELECT A.CNO AS CNO, A.FNO AS FNO, A.CID AS CID, A.IID AS IID
    FROM CAC_LKP A, (SELECT C_DATE, CNO, FNO
    FROM (SELECT MAX(CAC_LKP.C_DATE) AS C_DATE, CAC_LKP.CNO AS CNO, CAC_LKP.FNO AS FNO
    FROM CAC_LKP
    WHERE ACTIVE = 'Y' GROUP BY CNO, FNO)) B
    WHERE A.C_DATE = B.C_DATE
    AND A.CNO = B.CNO
    AND A.FNO = B.FNO
    AND A.ACTIVE = 'Y'
    Primary key is defied over combination of c_date,iid,active.
    Edited by: 1009236 on Jun 1, 2013 12:52 AM

    >
    SELECT  A.CNO AS CNO,
            A.FNO AS FNO,
            A.CID AS CID,
            A.IID AS IID
    FROM    CAC_LKP A,
                            SELECT  C_DATE,
                                    CNO,
                                    FNO
                            FROM
                                SELECT  MAX(CAC_LKP.C_DATE) AS C_DATE,
                                        CAC_LKP.CNO AS CNO,
                                        CAC_LKP.FNO AS FNO
                                FROM CAC_LKP
                                WHERE ACTIVE = 'Y'
                                GROUP BY CNO, FNO
                        ) B
    WHERE   A.C_DATE = B.C_DATE     AND
            A.CNO = B.CNO           AND
            A.FNO = B.FNO           AND
            A.ACTIVE = 'Y';Hi,
    Before even starting to see why there is a performance problem, I think you should consider the fact that there is logical problem in your WHERE clause. According to what you mentioned the primary key is composed of *(c_date, iid, active)* yet iid is absent in both the global query's WHERE clause and also that of the subquery.
    Consequently the (aggregate) rows in the subquery will not be linked based on a correct logic to the external query.
    Regards,
    Dariyoosh

  • How to re-write this self join update using a CTE

    I would like to improve my performance on this update statement and would like to try re-writing using a CTE:
    UPDATE "usr_sessions" "a" SET "is_ended_at_trustable" = 't'
          WHERE (
            EXISTS (
              SELECT 1
              FROM "usr_sessions" "b"
              WHERE "a"."ended_at" = "b"."started_at"
                AND "a"."usr_space_id" = "b"."usr_space_id"
                AND "a"."account_id" = "b"."account_id"
          ) ) AND "a"."is_ended_at_trustable" IS NULL
    Any help is greatly appreciated!  Open to other suggestions as well if there is a better way!

    If I understood your description correctly, here's a way to accomplish the same thing, while dodging the need for the self join.   The update itself won't be any faster, but the overall query leading to the update will likely be faster sans self-join.
      (If my interpretation wasn't exactly what you meant, tweak the "partition by" clause).
    MERGE is generally considered better then UPDATE, but your particular update isn't at risk for the shortcomings of update (still, Merge is newer, cooler, and more trustworthy).
    Setup_Example_Data:
    Declare @Usr_Sessions table (account_id int, usr_space_id int, is_ended_at_Trustable Char(1), started_at varchar(99), ended_at varchar(99))
    Insert @Usr_Sessions
    Select 1, 10, 't', 'A1', 'A1'
    UNION ALL Select 2, 20, 'f', 'B1', 'B2'
    UNION ALL Select 3, 30, NULL, 'C1', 'C1'
    UNION ALL Select 4, 40, NULL, 'D1', 'D2'
    UNION ALL Select 5, 50, NULL, 'E1', 'E2'
    UNION ALL Select 5, 51, NULL, 'E3', 'E3'
    UNION ALL Select 6, 61, NULL, 'F1', 'F2'
    UNION ALL Select 6, 62, 't', 'F3', 'F3'
    UNION ALL Select 6, 62, 'f', 'F4', 'F4'
    Select 'Before', * from @Usr_Sessions
    OP_Query:
    BEGIN TRAN
    UPDATE A SET is_ended_at_trustable = 't' from @usr_Sessions A-- Select * from @Usr_Sessions "a" --
    WHERE (
    EXISTS (
    SELECT 1
    FROM @usr_sessions "b"
    WHERE "a"."ended_at" = "b"."started_at"
    AND "a"."usr_space_id" = "b"."usr_space_id"
    AND "a"."account_id" = "b"."account_id"
    ) ) AND "a"."is_ended_at_trustable" IS NULL
    Select 'After 1', * from @Usr_Sessions
    ROLLBACK TRAN /* Just to reset test data to original form, so second query below runs against original data */
    Dodge_Self_Join:
    With X as
    Select *
    , count(case when started_at = ended_at and is_ended_at_trustable is null then 'x' else null end)
    over(partition by account_id, usr_space_id) as Updatable
    From @Usr_Sessions
    Update X
    set is_ended_at_Trustable = 'T'
    where Updatable > 0 -- EDIT -- fixed error, previously said "updatable = 1"
    Select 'After 2', * from @Usr_Sessions

  • Recursive Self Join

    Hi. I need to query the database of a document management system.   Documents are logically stored in folders in a tree structure and may be nested to arbitrary depth.  The FOLDER table lists the names and metadata of folders. 
    Ultimately, I want to join the FOLDER table ("f") to the DOCUMENT table ("d") to get a list of documents by folder.  The main thing I need help with is to build folder paths.  I don't necessarily even
    need to build full paths.  I would be happy just listing all the individual folders under the root, and the documents they contain.  I imagine to build folder paths involves a self join, but I don't know how to hadle arbitrary depth
    The first two columns of the FOLDER table are FOLDER_ID and PARENT_FOLDER_ID.  The data looks like this (where FOLDER_ID 1 represents the root folder):
    FOLDER_ID     PARENT_FOLDER_ID
    1                    null
    2                    1
    3                    1
    4                    1
    5                    2
    6                    2
    7                    1
    etc.
    Thanks for your help!

    See Itzik Ben-Gan examples dealing with such queries.
    CREATE TABLE Employees
      empid   int         NOT NULL,
      mgrid   int         NULL,
      empname varchar(25) NOT NULL,
      salary  money       NOT NULL,
      CONSTRAINT PK_Employees PRIMARY KEY(empid),
      CONSTRAINT FK_Employees_mgrid_empid
        FOREIGN KEY(mgrid)
        REFERENCES Employees(empid)
    CREATE INDEX idx_nci_mgrid ON Employees(mgrid)
    SET NOCOUNT ON
    INSERT INTO Employees VALUES(1 , NULL, 'Nancy'   , $10000.00)
    INSERT INTO Employees VALUES(2 , 1   , 'Andrew'  , $5000.00)
    INSERT INTO Employees VALUES(3 , 1   , 'Janet'   , $5000.00)
    INSERT INTO Employees VALUES(4 , 1   , 'Margaret', $5000.00) 
    INSERT INTO Employees VALUES(5 , 2   , 'Steven'  , $2500.00)
    INSERT INTO Employees VALUES(6 , 2   , 'Michael' , $2500.00)
    INSERT INTO Employees VALUES(7 , 3   , 'Robert'  , $2500.00)
    INSERT INTO Employees VALUES(8 , 3   , 'Laura'   , $2500.00)
    INSERT INTO Employees VALUES(9 , 3   , 'Ann'     , $2500.00)
    INSERT INTO Employees VALUES(10, 4   , 'Ina'     , $2500.00)
    INSERT INTO Employees VALUES(11, 7   , 'David'   , $2000.00)
    INSERT INTO Employees VALUES(12, 7   , 'Ron'     , $2000.00)
    INSERT INTO Employees VALUES(13, 7   , 'Dan'     , $2000.00)
    INSERT INTO Employees VALUES(14, 11  , 'James'   , $1500.00)
    The first request is probably the most common one:
     returning an employee (for example, Robert whose empid=7) 
    and his/her subordinates in all levels. 
    The following CTE provides a solution to this request:
    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS
      -- Anchor Member (AM)
      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 7
      UNION ALL
      -- Recursive Member (RM)
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees AS E
        JOIN EmpCTE AS M
          ON E.mgrid = M.empid
    SELECT * FROM EmpCTE
    Using this level counter you can limit the number of iterations
     in the recursion. For example, the following CTE is used to return 
    all employees who are two levels below Janet:
    WITH EmpCTEJanet(empid, empname, mgrid, lvl)
    AS
      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 3
      UNION ALL
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTEJanet as M
          ON E.mgrid = M.empid
      WHERE lvl < 2
    SELECT empid, empname
    FROM EmpCTEJanet
    WHERE lvl = 2
    As mentioned earlier, CTEs can refer to
     local variables that are defined within the same batch.
     For example, to make the query more generic, you can use 
    variables instead of constants for employee ID and level:
    DECLARE @empid AS INT, @lvl AS INT
    SET @empid = 3 -- Janet
    SET @lvl   = 2 -- two levels
    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS
      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = @empid
      UNION ALL
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTE as M
          ON E.mgrid = M.empid
      WHERE lvl < @lvl
    SELECT empid, empname
    FROM EmpCTE
    WHERE lvl = @lvl
    Results generated thus far might be returned (but are not guaranteed to be), 
    and error 530 is generated. You might think of using the MAXRECURSION option 
    to implement the request to return employees who are two levels below 
    Janet using the MAXRECURSION hint instead of the filter in the recursive member
    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS
      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 1
      UNION ALL
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTE as M
          ON E.mgrid = M.empid
    SELECT * FROM EmpCTE
    OPTION (MAXRECURSION 2)
    WITH EmpCTE(empid, empname, mgrid, lvl, sortcol)
    AS
      SELECT empid, empname, mgrid, 0,
        CAST(empid AS VARBINARY(900))
      FROM Employees
      WHERE empid = 1
      UNION ALL
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1,
        CAST(sortcol + CAST(E.empid AS BINARY(4)) AS VARBINARY(900))
      FROM Employees AS E
        JOIN EmpCTE AS M
          ON E.mgrid = M.empid
    SELECT
      REPLICATE(' | ', lvl)
        + '(' + (CAST(empid AS VARCHAR(10))) + ') '
        + empname AS empname
    FROM EmpCTE
    ORDER BY sortcol
    (1) Nancy
     | (2) Andrew
     |  | (5) Steven
     |  | (6) Michael
     | (3) Janet
     |  | (7) Robert
     |  |  | (11) David
     |  |  |  | (14) James
     |  |  | (12) Ron
     |  |  | (13) Dan
     |  | (8) Laura
     |  | (9) Ann
     | (4) Margaret
     |  | (10) Ina
    Best Regards,Uri Dimant SQL Server MVP,
    http://sqlblog.com/blogs/uri_dimant/
    MS SQL optimization: MS SQL Development and Optimization
    MS SQL Consulting:
    Large scale of database and data cleansing
    Remote DBA Services:
    Improves MS SQL Database Performance
    SQL Server Integration Services:
    Business Intelligence

  • Partition by clause

    Dose the Partition by clause increase the perfomance then the normal group by clause ??
    thanks,
    Raj.

    Analytic queries != Aggregate queries
    Therefore it depends on what you're doing as to whether you'd want to use Analytic vs Aggregate queries.
    Performance depends also on the amount of data in your tables.
    Having said that, Analytics can mean that a self-join is no longer needed, and this could help if a large table is involved ... on the otherhand, it might hinder.
    Think of Analytic queries as another tool in your toolbox; sometimes a hammer is the right tool to use, but sometimes you need a spanner instead.

  • Self join please help

    I would be very grateful if someone would show me show to use the self join, I understand what is does but just don't know how to use it. I have a question from a exercise but no answer so I can't check it the question is - using temporary labels to abbreviate table names, find all the staff that earn more than 'SONG'.
    here is the table
    STAFFID SNAME JOB MGR STARTDATE SAL COMM BRANCHID
    5963 SMITH ADMIN 5209 15-NOV-00 1600 20
    5994 BATES ASSISTANT 5896 20-FEB-01 1800 100 30
    5125 CHAN ASSISTANT 5896 22-FEB-02 1550 150 30
    5665 JONES MANAGER 5938 02-MAR-01 3100 20
    5465 WILSON ASSISTANT 5896 28-OCT-00 1250 140 30
    5896 HAYAT MANAGER 5938 01-MAY-01 3100 30
    5287 CLARK MANAGER 5938 09-JUL-02 3100 10
    5887 COSTA BUYER 5665 18-APR-04 3150 20
    5938 SHAW DIRECTOR 17-NOV-01 7000 10
    5484 TURNER ASSISTANT 5896 08-OCT-01 1550 0 30
    5678 KALIM ADMIN 5887 23-APR-04 1600 20
    5009 JAMES ADMIN 5896 03-DEC-01 1600 30
    5209 SONG BUYER 5665 03-JAN-02 3000 20
    5439 SIMPSON ADMIN 5287 23-FEB-02 1600 10
    Thanks in advanced :)
    Edited by: user11093259 on 01-Dec-2010 10:19

    Hi,
    Welcome to the forum!
    Always post your best attempt at solving the problem. You'll get more specific replies that will help you learn more, and it often clarifies what you're trying to do.
    Here's a typical self-join, using the scott.dept table (which you probably have avaialble).
    SELECT     l.dname          AS lower_dname
    ,     h.dname          AS higher_dname
    FROM     scott.dept     l
    JOIN     scott.dept     h  ON     l.dname     < h.dname
    ;Output:
    LOWER_DNAME    HIGHER_DNAME
    ACCOUNTING     OPERATIONS
    ACCOUNTING     RESEARCH
    ACCOUNTING     SALES
    OPERATIONS     RESEARCH
    OPERATIONS     SALES
    RESEARCH       SALESAs you can see, this pairs every higher_dname with every dname that is less than it.
    This is very similar to your problem. The main difference is, where the query above shows every possible higher_dname (and the lower_dnames related to it), you're interested in a single, specific higher value (and the rolws with lower values related to it). You can restrict the query to show only that one, specific higher values by adding a WHERE clause. Try it. If you get stuck, ask a more specific question, and, remember, post your code.

  • Self join vs Hierarchical Queries

    Hi,
    please tel me which one 1 should use ?
    i have to get simple manger's employ list, should i use self join or hierarchical queries(CONNECT BY and prior)?
    yours sincerely

    Hi,
    944768 wrote:
    Hi,
    please tel me which one 1 should use ?
    i have to get simple manger's employ list, should i use self join or hierarchical queries(CONNECT BY and prior)?It depends on your data and your requirements.
    Whenever you have a question, please post a little sample data (CREATE TABLE and INSERT statements) for all the tables involved, so the people who want to help you can re-create the problem and test their ideas. Also post the results you want from that data, and an explanation of how you get those results from that data.
    Explain, using specific examples, how you get those results from that data.
    If you can show what the problem is using commonly available tables (suc as scott.emp, which has a 4-level hierarchy) then you don't have ot post any sample data, just the results and the explanation.
    Always say what version of Oracle you're using (e.g. 11.2.0.2.0).
    See the forum FAQ {message:id=9360002}
    If your hierarchy consists only of 2 levels, then a self-join will probably be more efficient, simpler to code, and easier to maintain.
    If you don't know how many levels are in the hierarchy, then self-join isn't an option. Use CONNECT BY or, if you have Oracle 11.2, a recursive WITH clause.
    If you have a fixed number of levels (or an upper bound) greater than 2, then CONNECT BY (or a recursive WITH clause) will probably be best.

Maybe you are looking for