SQL challenge: avoid this self-join!!!

Here's something of a challenging SQL problem. I'm trying to persist an arbitrary number of attributes for an object. I am trying to do this in a regular relational table both for performance and to make future upgrades easier.
The problem is that I don't know what SQL cleverness I can use to only scan the ATTR table once.
Does Oracle (or for that matter the SQL standard) have some way to help me? Here's a simplified example:
Consider a table ATTR with columns OID, ATTR_ID, ATTR_VAL. Unique key is OID, ATTR_ID. Assume any other indexes that you want, but be aware that ATTR_VAL is modestly dynamic.
I can easily look for a OID for any one ATTR_ID, ATTR_VAL pair:
SELECT oid FROM attr
WHERE attr_id = 1 AND attr_val = :b1
I can also easily do this looking at multiple attributes when I only need one condition to be met with an OR, as:
SELECT DISTINCT oid FROM attr
WHERE (attr_id = 1 AND attr_val = :b1)
OR (attr_id = 31 AND attr_val = :b2)
But how to handle the condition where I want to have the two ATTR_ID, ATTR_VAL pairs "and-ed" together? I know that I can do this:
SELECT oid FROM
(SELECT oid FROM attr WHERE attr_id = 1 AND attr_val = :b1)
UNION
(SELECT oid FROM attr WHERE attr_id = 31 AND attr_val = :b2)
But this will necessitate looking at ATTR twice. This is maybe okay if there are only two conditions, but what about when there might be 10 or even 50? At some point this technique becomes unacceptable.
Clearly:
SELECT DISTINCT oid FROM attr
WHERE (attr_id = 1 AND attr_val = :b1)
AND (attr_id = 31 AND attr_val = :b2)
won't work (each row has but one ATTR_ID).
The following will end up doing the same basic thing as the UNION (it avoids a sort so is preferable):
SELECT oid FROM attr a1, attr a2
WHERE a1.oid = a2.oid
AND (a1.attr_id = 1 AND a1.attr_val = :b1)
AND (a2.attr_id = 31 AND a2.attr_val = :b2)
but the fundamental problem of scanning ATTR twice remains.
What cleverness can I apply here to only scan ATTR once?
Thanks,
:-Phil

An other way of having a dynamic in list build from a singel string is show at asktom at this link http://asktom.oracle.com/pls/ask/f?p=4950:8:2019864::NO::F4950_P8_DISPLAYID,F4950_P8_CRITERIA:210612357425,%7Bvarying%7D%20and%20%7Belements%7D%20and%20%7Bin%7D%20and%20%7Bin%7D%20and%20%7Blist%7D
an modified version for two columns:
Create or replace type in_list as object (col1 varchar2(20), col2 varchar2(30));
Create or replace type in_list_tab as table of in_list;
Create or replace function fn_in_list( p_string in varchar2) return in_list_tab
as
l_string long default p_string || ',';
l_data in_list_tab := in_list_tab();
pos number;
begin
pos := 0;
loop
exit when l_string is null;
pos := instr( l_string, ',' );
l_data.extend;
l_data(l_data.count) := in_list('','');
l_data(l_data.count).col1 := ltrim(rtrim(substr(l_string, 1, pos - 1)));
l_string := substr( l_string, pos + 1 );
if l_string is null
then
     l_data.Trim;
     exit;
end if;
pos := instr( l_string, ',' );
l_data(l_data.count).col2 := ltrim(rtrim(substr(l_string, 1, pos - 1)));
l_string := substr( l_string, pos + 1 );
end loop;
return l_data;
end;
create table testII (cola varchar2(10), colb varchar2(30));
insert into testII values ('abc',1);
insert into testII values ('abc',2);
insert into testII values ('def',1);
insert into testII values ('def',2);
commit;
var b1 varchar2(200);
exec :b1:='abc,1,def,2';
select * from testII where (cola,colb) in
(select col1, col2 from THE ( select cast(fn_in_list(:b1) as in_list_tab) from dual));
to handle cases like
attr_id = 41 and attr_val > :b3 I would say dynmaic SQL

Similar Messages

  • 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

  • How to write self join in sql?

    Hi,
    I have table named "table_upload", column "record_type" value "01,03,04....." and start_date,end_date and so on
    And i will have value for  start_date,end_date only for record_type=01,rest of type these two columns will be null.
    now i need to write query with self join, to include above concept. can any one please help me .
    and my query look like follows,

    I just want to re write
    Please provide DDL+DML + expected output!
    and short explanation what is it that we all ask you for:
    DDL = Data Definition Language. In our case that is, CREATE TABLE statements for your tables and other definitions that are needed to understand your tables structure and there for let us to test and reproduce the problem in our server. Without DDL no one
    can execute any query.
    How to get DDL: Right click on the table in Object Explorer and select script table as CREATE. Post these create table scripts here.
    DML = data manipulation language is a family of queries used for manipulating the data it self like: inserting, deleting and updating data. In our case we need some sample data in order to check the query and get result, so we need some indert query for
    sample data.
    If you post a "create table query" for the tables and "insert <table> query" with some sample, then we could help you without Assuming/Guessing. There is a reason that DDL is generally asked for and expected when discussing query problems - it helps
    to identify issues, clarify terminology and prevent incorrect assumptions.  Sample data also provides a common point of reference for the discussion. A script that can be used to illustrate or reproduce the issue you have, will encourage others to help.
    [Personal Site] [Blog] [Facebook]

  • How to Avoid Self Join

    Hi
    Assume I have following table
    Id Code
    1 aa
    1 bb
    1 cc
    2 bb
    2 cc
    The records will be grouped by Id. I want to find out group containing code say 'aa' and 'bb'.
    Is it possible to obtain the desired result in a single query without using Self join?
    Regards
    ~Pravin

    This is a little clumsy....Anyway try it:
    WITH t AS
    (SELECT 1 id,'aa' code FROM dual
    UNION ALL
    SELECT 1,'bb' FROM dual
    UNION ALL
    SELECT 1,'cc' FROM dual
    UNION ALL
    SELECT 2,'bb' FROM dual
    UNION ALL
    SELECT 2,'cc' FROM dual)
    SELECT id FROM t
    WHERE code IN('aa', 'bb')
    GROUP BY id HAVING COUNT(*) = 2;

  • Oracle doc inconsistent on materialize view with union all and self joins

    First of all, I can't seem to create a materialized view containing self-joins AND union all. Is it possible?
    I checked Oracle 9i (my version: PL/SQL Release 9.2.0.4.0 - Production) documentation and I get different answers (or so it seems to me).
    First I saw this: "The COMPATIBILITY parameter must be set to 9.0 if the materialized aggregate view has inline views, outer joins, self joins or grouping sets and FAST REFRESH is specified during creation..."
    Did you see the part about 'self joins' in there? I did and I was pumped because that seems to say that you CAN have 'self joins' (and my compatibility is 9.2...)
    BUT
    In the very same document I also found "Oracle does not allow self-joins in materialized join views." (rage)
    You can see the document I am speaking of here: http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96520/mv.htm#574889
    Whenever I try to create the mview I get the following error. (
    In any caseORA-01446 cannot select ROWID from view with DISTINCT, GROUP BY, etc.

    First of all, I can't seem to create a materialized view containing self-joins AND union all. Is it possible?
    I checked Oracle 9i (my version: PL/SQL Release 9.2.0.4.0 - Production) documentation and I get different answers (or so it seems to me).
    First I saw this: "The COMPATIBILITY parameter must be set to 9.0 if the materialized aggregate view has inline views, outer joins, self joins or grouping sets and FAST REFRESH is specified during creation..."
    Did you see the part about 'self joins' in there? I did and I was pumped because that seems to say that you CAN have 'self joins' (and my compatibility is 9.2...)
    BUT
    In the very same document I also found "Oracle does not allow self-joins in materialized join views." (rage)
    You can see the document I am speaking of here: http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96520/mv.htm#574889
    Whenever I try to create the mview I get the following error. (
    In any caseORA-01446 cannot select ROWID from view with DISTINCT, GROUP BY, etc.

  • Student learning, self join

    Our teacher isnt very clear on self joins, and searching brings up too complicated of info for someone like myself just learning, so i was hoping you guys could help out. Table below:
    SQL> select * from grade;
    STD_CODE GR_LNAME GR_FNAME GR_T1 GR_T2 GR_HW GR_PR
    S1 Jordan Michael 95 80 98 90
    S2 Barkley Charles 60 100 100 60
    S3 Johnson Magic 88 98 96 98
    S4 Williams Serena 92 92 92 92
    S5 Duncan Tim 94 90 94 96
    S6 Graff Steffi 85 84 83 72
    S7 Navratilova Martina 91 88 94 95
    Need to solve this question:
    Create a view that will display names of students that have identical average grade (average of gr_t1, t2, hw, and pr)
    I learned that we needed to create a self join to sniff out the averages that were the same.
    I am pretty clueless on the logic of self join, but I made an attempt:
    CREATE VIEW SAME_GRADES2 AS SELECT S.STD_FNAME, S.STD_LNAME, (GR_T1+GR_T2+GR_HW+GR_PR)/4 AVG_GR
    FROM GRADE S, GRADE G
    WHERE S.AVG_GR=G.AVG_GR;
    i get an error on this: ORA-00904: "G"."AVG_GR": invalid identifier
    No idea. Any help for a newbie?

    sorry that last one was a syntax error... here is the result (obviously not what i need)
    GR_FNAME GR_LNAME AVG_GR
    Michael________Jordan____________90.75
    Charles________Barkley____________80
    Magic________Johnson____________95
    Martina________Navratilova_________92
    Serena________Williams____________92
    Tim________Duncan______________93.5
    Steffi________Graff _______________81
    Martina________Navratilova _________92
    Serena________Williams____________92
    9 rows selected.
    code:
    CREATE VIEW SAME_GRADES2 AS SELECT S.GR_FNAME, S.GR_LNAME, (S.GR_T1+S.GR_T2+S.GR_HW+S.GR_PR)/4 AVG_GR
    FROM GRADE S, GRADE G GROUP BY S.GR_FNAME
    WHERE (S.GR_T1+S.GR_T2+S.GR_HW+S.GR_PR)/4 = (G.GR_T1+G.GR_T2+G.GR_HW+G.GR_PR)/4;
    Edited by: user10188205 on Oct 22, 2008 4:42 PM

  • 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

  • Set operator Vs Self join

    hi all,
    i have a main table and a corresponding history table.
    Like employee and h_employee both has primary key as emp_id.
    now i want a query which should only retrieve the common values among these two table.
    I have an idea of doing this in two way 1.self join 2. set operator
    1.select emp_id
    from emp e,h_emp h
    using (emp_id)
    2. select emp_id from emp
    intersect
    select emp_id from h_emp
    now guide me which gives better performance? how to evaluate the performance in PL/SQL Developer client?
    is there any keyword to trace the timing of the each query?
    Please advice.
    Regards,
    Slu

    Set operators combines the output of 2 or more queries into single output....
    Internally its doing sorting the two tables
    Join is just matching the records based on the where condition ....
    use Explain plan to the cost of the query
    SQL> Explain plan for select emp_id
    from emp e,h_emp h
    using (emp_id)
    and use
    SQL > select * from plan_table
    to see the cost...
    Edited by: LPS on Jul 12, 2011 12:08 AM

  • 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

  • How to perform a self-join in WebI?

    Post Author: willgreenland
    CA Forum: WebIntelligence Reporting
    I want to perform a self-join on a table in WebI, in order to achieve the following result (of course, if there is another way of doing this I'd be glad to hear it):
    I have a table that lists the department in which an employee is located at given dates in the past:
    EMPLID    DEPT    DATE
    123                Sales    2007...
      I want to use this table to track migration between departments, in other words I want to produce the following output table, showing how in 2008, 5 employees moved from Sales to Marketing (etc):DEPT_A    DATE_A    DEPT_B    DATE_B    COUNT(EMPLID) Sales        2007          Mrkting      2008             5...
    In order to do this in SQL, I would do the following:
    SELECT a.DEPT, b.DEPT, count(distinct EMPLID)FROMEMPL_DEPT a, EMPL_DEPT b        // note the self-join hereWHERE( a.EMPLID = b.EMPLID AND a.DATE = '2007' AND b.DATE = '2008' )GROUP BY a.DEPT, b.DEPT;
    Is there a way of doing this in WebI, ideally without resorting to manual SQL editing (I want this to be a report that other users can make sense of without necessarily getting into the SQL)?

    Post Author: amr_foci
    CA Forum: WebIntelligence Reporting
    you cant do something like that in the WebI directly, you have to manager that at the unvinerse level first
    good luck

  • 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

  • URGENT self join problem

    SQL> desc messages;
    Name Null? Type
    MESSAGEID NOT NULL NUMBER
    TITLE NOT NULL VARCHAR2(50)
    AUTHOR VARCHAR2(20)
    BODY NOT NULL VARCHAR2(4000)
    BOARD NUMBER
    THREAD NOT NULL NUMBER
    DATE_CREATED NOT NULL DATE
    This is the table i need to do a self join on, i know the two queries individually but i need to have them in one join,,,
    select b.title,b.boardid,m.messageid,m.title,m.author,m.date_created,m.body
    from messages m, boards b where b.boardid=m.board and m.thread=0 and b.boardid='198'
    and m.messageid='241';
    Thread title Author Starting message Last post
    Austrailia noel Austrailia 04/01/2005 21:22:35
    -----selects replies to the above message-----------
    select author,date_created,body
    from messages
    where board=198 and thread=241;
    AUTHOR DATE_CREATED BODY
    noel           05-JAN-05 Oz is played on clay
    noel 05-JAN-05 Oz played on grass
    noel 05-JAN-05     Oz played on grass
    This is the output that i want but at the moment thread title is repeated for all four rows returned.I want the output to look like a reply to a message like you see in some message boards on the web,,, you have the starting message and underneath you see the replies
    Thread title Author Starting message Last post
    Austrailia noel Austrailia 04/01/2005
    noel Oz is played on clay 05-JAN-05
    noel Oz played on grass 05-JAN-05
    noel Oz played on grass 05-JAN-05

    Please please please do not post duplicate threads. It makes it hard for people to follow what's going on. And it's annoying to boot. I think this is the third thread you have started on this topic.
    Please remember we are volunteers here, not Oracle employees. We do the best we can to answer queries in a timely fashion but if you want snappier service then I'm afraid you'll need to pay for a support contract.
    You posted a rejoinder to Barbara's answer to your other thread URGENT: combining two sql statements. That is sufficient to keep your issue in the public arena.
    Thank you for your co-operation.
    Regards, APC
    Issued in memory of the Rogue Moderators

  • How to achieve parent-child relationship using self join?

    my table structure is as follows
    parent child name
    -1     1     A1
    1     2     A2
    1     3     A3
    how to achieve the hierarchy model using self join. this can be easily achieved using "connect by prior". but how to achieve the same using self join?

    Hi,
    Yes, that's definitely possible. If you only need to display two levels from the hierarchy, a self-join is a good option. Make it an outer join if you need to show everyone on one level, regardless of whether they have a match on the other level or not; for example, if you want the output:
    child_name     child_id     parent_name     parent_id
    A1          1
    A2          2          A1          1
    A3          3          A1          1It's good that you posted some sample data. Now post the results you want from that data, and your query (what you think is the best attempt you've made so far). If you haven't tried anything so far, then look at some other simple self-join to get ideas.

  • Problem writing a XSLT to convert XML in desired format from a table having self join

    Hello,
    I have to write a style sheet to convert XML generated from XSQL into a different format. The query that I have is as follows.
    select LEVEL depth,
    'H' || hierarchy_id id,
    name,
    nvl2(parent_id, 'H' || parent_id, 0) parent_id,
    CURSOR(select LEVEL depth,
    'H' || hierarchy_id hid,
    name hname,
    nvl2(parent_id, 'H' || parent_id, 0) hparent_id,
    decode(system_id, NULL, '0', 'S' || system_id) formatted_system_id,
    system_id
    from hierarchy
    where parent_id = h.hierarchy_id
    and system_id is not null
    ) as systems
    from hierarchy h
    where system_id is null
    start with parent_id is null
    connect by prior hierarchy_id = parent_id
    The hierarchy table has a self join to itself. The selfjoin is on the hierarchyid and the parentid fields which is evident from the query.
    Here the hierarchy table contains the parent system and also the child systems underneath. The problem is that the no. of levels that it can go deep is not fixed. The output of this in sqlplus is as follows.
    Depth Hierarchyid, name parentid
    1 h1 xxx <null>
    2 h2 bbb h1
    3 h3 ccc h2
    <Cursor for systems>
    hid hname hparentid formatted_system_id systemid
    h4 ccc h2 s1 1
    h5 ccc h2 s2 2
    <Back to original data>
    Depth Hierarchyid, name parentid
    2 h6 ddd h1
    2 h7 eee h1
    The desired output required from the stylesheet is as follows
    <h id=h1 name=xxx>
    <h id=h2 name=bbb parentid=h1>
    <h id=h3 name=ccc parentid=h2>
    <h id=h4 name=fff parentid=h3 systemid=s1>
    <h id=h5 name=ggg parentid=h3 systemid=s2>
    </h>
    </h>
    <h id=h6 name=ddd parentid=h1/>
    <h id=h7 name=eee parentid=h1/>
    </h>
    Could some one guide me as to how to get this. I did write a stylesheet which gives me the following output.
    <h id=h1 name=xxx>
    <h id=h2 name=bbb parentid=h1/>
    <h id=h3 name=ccc parentid=h2/>
    <h id=h4 name=fff parentid=h3 systemid=s1>
    <h id=h5 name=ggg parentid=h3 systemid=s2>
    </h>
    <h id=h6 name=ddd parentid=h1/>
    <h id=h7 name=eee parentid=h1/>
    </h>
    As you can see I am missing the closing of the tag on the 7th line in the desired format. I have written the following stylesheet.
    <!-- Hierarchy.xsl: Transform ROWSET/ROW format to the required Hierarchy format. -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    </xsl:template>
    <!-- Template for matching the rowset..... -->
    <xsl:template match="HIERARCHY">
    <HIERARCHY><xsl:apply-templates/></HIERARCHY>
    </xsl:template>
    <!-- Template for matching the row .... -->
    <xsl:template match="HELEMENT">
    <xsl:choose>
    <xsl:when test="PARENT_ID=0">
    <helement id="{ID}" name="{NAME}" parentid="{PARENT_ID}"/>
    </xsl:when>
    <xsl:when test="PARENT_ID!='0'">
    <helement2 id="{ID}" name="{NAME}" parentid="{PARENT_ID}">
    <xsl:for-each select="SYSTEMS/SYSTEMS_ROW">
    <helement3 id="{HID}" name="{HNAME}" parentid="{HPARENT_ID}" systemid="{FORMATTED_SYSTEM_ID}">
    </helement3>
    </xsl:for-each>
    </helement2>
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
    </xsl:stylesheet>
    Is there any way of achieving this. Any help would be appreciated. I am using XSQL to generate first the basic XML output and then applying stylesheet to achieve the desired output.
    Sincerely,
    D

    Hello,
    I have to write a style sheet to convert XML generated from XSQL into a different format. The query that I have is as follows.
    select LEVEL depth,
    'H' || hierarchy_id id,
    name,
    nvl2(parent_id, 'H' || parent_id, 0) parent_id,
    CURSOR(select LEVEL depth,
    'H' || hierarchy_id hid,
    name hname,
    nvl2(parent_id, 'H' || parent_id, 0) hparent_id,
    decode(system_id, NULL, '0', 'S' || system_id) formatted_system_id,
    system_id
    from hierarchy
    where parent_id = h.hierarchy_id
    and system_id is not null
    ) as systems
    from hierarchy h
    where system_id is null
    start with parent_id is null
    connect by prior hierarchy_id = parent_id
    The hierarchy table has a self join to itself. The selfjoin is on the hierarchyid and the parentid fields which is evident from the query.
    Here the hierarchy table contains the parent system and also the child systems underneath. The problem is that the no. of levels that it can go deep is not fixed. The output of this in sqlplus is as follows.
    Depth Hierarchyid, name parentid
    1 h1 xxx <null>
    2 h2 bbb h1
    3 h3 ccc h2
    <Cursor for systems>
    hid hname hparentid formatted_system_id systemid
    h4 ccc h2 s1 1
    h5 ccc h2 s2 2
    <Back to original data>
    Depth Hierarchyid, name parentid
    2 h6 ddd h1
    2 h7 eee h1
    The desired output required from the stylesheet is as follows
    <h id=h1 name=xxx>
    <h id=h2 name=bbb parentid=h1>
    <h id=h3 name=ccc parentid=h2>
    <h id=h4 name=fff parentid=h3 systemid=s1>
    <h id=h5 name=ggg parentid=h3 systemid=s2>
    </h>
    </h>
    <h id=h6 name=ddd parentid=h1/>
    <h id=h7 name=eee parentid=h1/>
    </h>
    Could some one guide me as to how to get this. I did write a stylesheet which gives me the following output.
    <h id=h1 name=xxx>
    <h id=h2 name=bbb parentid=h1/>
    <h id=h3 name=ccc parentid=h2/>
    <h id=h4 name=fff parentid=h3 systemid=s1>
    <h id=h5 name=ggg parentid=h3 systemid=s2>
    </h>
    <h id=h6 name=ddd parentid=h1/>
    <h id=h7 name=eee parentid=h1/>
    </h>
    As you can see I am missing the closing of the tag on the 7th line in the desired format. I have written the following stylesheet.
    <!-- Hierarchy.xsl: Transform ROWSET/ROW format to the required Hierarchy format. -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    </xsl:template>
    <!-- Template for matching the rowset..... -->
    <xsl:template match="HIERARCHY">
    <HIERARCHY><xsl:apply-templates/></HIERARCHY>
    </xsl:template>
    <!-- Template for matching the row .... -->
    <xsl:template match="HELEMENT">
    <xsl:choose>
    <xsl:when test="PARENT_ID=0">
    <helement id="{ID}" name="{NAME}" parentid="{PARENT_ID}"/>
    </xsl:when>
    <xsl:when test="PARENT_ID!='0'">
    <helement2 id="{ID}" name="{NAME}" parentid="{PARENT_ID}">
    <xsl:for-each select="SYSTEMS/SYSTEMS_ROW">
    <helement3 id="{HID}" name="{HNAME}" parentid="{HPARENT_ID}" systemid="{FORMATTED_SYSTEM_ID}">
    </helement3>
    </xsl:for-each>
    </helement2>
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
    </xsl:stylesheet>
    Is there any way of achieving this. Any help would be appreciated. I am using XSQL to generate first the basic XML output and then applying stylesheet to achieve the desired output.
    Sincerely,
    D

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

Maybe you are looking for

  • Answers to these ABAP Questions

    Hi Everyone, It would very nice of your guys to answer these questions for me. <b>1.     Which is related to Debugging function?       1.Modify     2. Continue     3. Switch 4.Change 2.     In DO and ENDDO the following statement occurs ? 1.     Read

  • My phone is not showing up as a device on Find iPhone

    I have a phone and an ipad. When I go to Find Iphone to try to add my device, I cannot. I have turned on the locations settings, I have rebooted, I have updated my iCloud password and turned "on" everything that needs to be on. I have seen no fixes o

  • Calling a pkg from managed code and then using reflection to call a method from a script task

    Hi we run 2012 std.  I have some pretty good evidence that when I call my pkg from a .net service, a script component in that pkg fails when trying 2 use reflection to load and invoke our .net message history method.  The exception is either on the i

  • Date Mapping Error in XI

    Hi, I have mapping date fields from sap r/3 which is in format yyyymmdd to yyyy-mm-dd format in XI using TransformDate function. I facing one probme here no matter whather month in source field while conversion it is getting convert as '01'. Eg, for

  • To send Mfr part nuber with  changed PO

    Hi Experts, I have a scenario of IDoc to cXML, Which we use to send. the PO and PO-change. The requirement is to send the Manufacturer Part number to cXML. 1. For the PO I have worked out the below mapping. [http://www.flickr.com/photos/25429360@N07/