Outer Join creating duplicated rows (sort of)

Greetings Forum,
Using version MII 11.5 sp 6
Joining two unique xml documents on three common columns using the Join Action block set up for an outer join.  The results of the join are
Set a          Set b           results in
c1   c2        c1   c3         c1   c2   c3
a    a1        a    a2         a    a1   a2
b    b1        b    b2         a    a1   ---    this row is extra
c    c1                        b    b1   b2
d    d1                        b    b1   ---    this row is extra
                               c    c1   ---
                               d    d1   ---
in this example the two extra rows match set a and not in set b even though they did have matching data.
Any Ideas.  We have tryed deleting the join action and recreating it.  Doing the join with two local xml documents....

Actually, It's three columns matched up to three columns.  Attached is an actual sample right out of BLS.
[INFO SET 1 ]: <?xml version="1.0" encoding="UTF-8"?><Rowsets DateCreated="2008-08-12T15:50:16" EndDate="2008-08-12T16:27:22" StartDate="2008-08-12T16:27:22" Version="11.5.3">
     <Rowset>
          <Columns>
               <Column Description="a" MaxRange="1" MinRange="0" Name="a" SQLDataType="1" SourceColumn="a"/>
               <Column Description="b" MaxRange="1" MinRange="0" Name="b" SQLDataType="1" SourceColumn="b"/>
               <Column Description="c" MaxRange="1" MinRange="0" Name="c" SQLDataType="1" SourceColumn="c"/>
               <Column Description="d" MaxRange="1" MinRange="0" Name="d" SQLDataType="8" SourceColumn="d"/>
          </Columns>
          <Row>
               <a>a1</a><b>b1</b><c>c1</c><d>d1</d>
          </Row>
          <Row>
               <a>a2</a><b>b2</b><c>c2</c><d>d2</d>
          </Row>
          <Row>
               <a>a3</a><b>b3</b><c>c3</c><d>d3</d>
          </Row>
          <Row>
               <a>a4</a><b>b4</b><c>c4</c><d>d4</d>
          </Row>
     </Rowset>
</Rowsets>
[INFO SET 2]: <?xml version="1.0" encoding="UTF-8"?><Rowsets DateCreated="2008-08-12T15:50:16" EndDate="2008-08-12T16:27:22" StartDate="2008-08-12T16:27:22" Version="11.5.3">
     <Rowset>
          <Columns>
               <Column Description="a" MaxRange="1" MinRange="0" Name="a" SQLDataType="1" SourceColumn="a"/>
               <Column Description="b" MaxRange="1" MinRange="0" Name="b" SQLDataType="1" SourceColumn="b"/>
               <Column Description="c" MaxRange="1" MinRange="0" Name="c" SQLDataType="1" SourceColumn="c"/>
               <Column Description="e" MaxRange="1" MinRange="0" Name="e" SQLDataType="1" SourceColumn="e"/>
          </Columns>
          <Row>
               <a>a1</a><b>b1</b><c>c1</c><e>e1</e>
          </Row>
          <Row>
               <a>a2</a><b>b2</b><c>c2</c><e>e2</e>
          </Row>
     </Rowset>
</Rowsets>
[INFO RESEULTs]: <?xml version="1.0" encoding="UTF-8"?><Rowsets DateCreated="2008-08-12T15:50:16" EndDate="2008-08-12T16:27:22" StartDate="2008-08-12T16:27:22" Version="10.0">
     <Rowset>
          <Columns>
               <Column Description="a" MaxRange="1" MinRange="0" Name="a" SQLDataType="1" SourceColumn="a"/>
               <Column Description="b" MaxRange="1" MinRange="0" Name="b" SQLDataType="1" SourceColumn="b"/>
               <Column Description="c" MaxRange="1" MinRange="0" Name="c" SQLDataType="1" SourceColumn="c"/>
               <Column Description="d" MaxRange="1" MinRange="0" Name="d" SQLDataType="8" SourceColumn="d"/>
               <Column Description="e" MaxRange="1" MinRange="0" Name="e" SQLDataType="1" SourceColumn="e"/>
          </Columns>
          <Row>
               <a>a1</a><b>b1</b><c>c1</c><d>d1</d><e>e1</e>
          </Row>
          <Row>
               <a>a1</a><b>b1</b><c>c1</c><d>d1</d><e>---</e>
          </Row>
          <Row>
               <a>a2</a><b>b2</b><c>c2</c><d>d2</d><e>e2</e>
          </Row>
          <Row>
               <a>a2</a><b>b2</b><c>c2</c><d>d2</d><e>---</e>
          </Row>
          <Row>
               <a>a3</a><b>b3</b><c>c3</c><d>d3</d><e>---</e>
          </Row>
          <Row>
               <a>a4</a><b>b4</b><c>c4</c><d>d4</d><e>---</e>
          </Row>
     </Rowset>
</Rowsets>

Similar Messages

  • Outer Join not returning rows

    Hi,
    i have a view based on the following statement. I can't get the unmatched rows from table 'npe' to show up in the result.
    SELECT DISTINCT rctla.customer_trx_id, msi.segment1 item_number,
                    rcta.trx_date trx_date, rcta.bill_to_customer_id cust_id,
                    (rctla.quantity_invoiced) * NVL (msi.attribute13, 1) quantity,
                    ROUND ((rctla.unit_selling_price * rctla.quantity_invoiced),
                           0
                          ) net_sales,
                    ROUND ((cic.material_cost * rctla.quantity_invoiced),
                           0
                          ) product_cost,
                    ROUND ((npe.expense * rctla.quantity_invoiced), 0) expense,
                    ROUND (  (rctla.unit_selling_price * rctla.quantity_invoiced
                           - (  cic.material_cost * rctla.quantity_invoiced
                              + rctla.quantity_invoiced * npe.expense
                           0
                          ) gp_dollars
               FROM ra_customer_trx_all rcta,
                    ra_customer_trx_lines_all rctla,
                    cst_cost_types cct,
                    cst_item_costs cic,
                    mtl_system_items_b msi,
                    nfpc.nfpc_gpm_expense npe,
                    hz_cust_accounts hca
              WHERE rcta.complete_flag = 'Y'
                AND rcta.interface_header_attribute1 NOT LIKE '%B'
                AND rcta.interface_header_context = 'ORDER ENTRY'
                AND rcta.batch_source_id IN (1068, 1069)
                AND rcta.customer_trx_id = rctla.customer_trx_id
                AND rctla.inventory_item_id = msi.inventory_item_id
                AND UPPER (cct.cost_type) = 'FROZEN'
                AND cic.cost_type_id = cct.cost_type_id
                AND cic.inventory_item_id = msi.inventory_item_id
                AND npe.customer_no = hca.account_number
                AND hca.cust_account_id = rcta.bill_to_customer_id
                AND rcta.trx_date BETWEEN '01-FEB-10' AND '01-FEB-10'
                AND rctla.inventory_item_id = npe.inventory_item_id(+)
                AND rctla.customer_trx_id = '903670';I know there are two inventory_item_id rows that are not in the nfpc_gpm_expense table but are in the 'rctla' and 'msi' tables.
    I am on RDBMS 9i .
    Thanks in advance for your time.
    A/A

    Hi Asgar,
    check if this helps:
    SELECT DISTINCT rctla.customer_trx_id, msi.segment1 item_number,
                    rcta.trx_date trx_date, rcta.bill_to_customer_id cust_id,
                    (rctla.quantity_invoiced) * NVL (msi.attribute13, 1) quantity,
                    ROUND ((rctla.unit_selling_price * rctla.quantity_invoiced),
                           0
                          ) net_sales,
                    ROUND ((cic.material_cost * rctla.quantity_invoiced),
                           0
                          ) product_cost,
                    ROUND (( nvl(npe.expense,1 ) * rctla.quantity_invoiced), 0) expense,   --included NVL
                    ROUND (  (rctla.unit_selling_price * rctla.quantity_invoiced
                           - (  cic.material_cost * rctla.quantity_invoiced
                              + rctla.quantity_invoiced * nvl(npe.expense,1 )                        --included NVL
                           0
                          ) gp_dollars
               FROM ra_customer_trx_all rcta,
                    ra_customer_trx_lines_all rctla,
                    cst_cost_types cct,
                    cst_item_costs cic,
                    mtl_system_items_b msi,
                    ( select nge.expense, nge.inventory_item_id, rctla2.customer_trx_line_id
                      from nfpc.nfpc_gpm_expense nge,
                           hz_cust_accounts_all hcaa,
                           ra_customer_trx_all rcta2,
                           ra_customer_trx_lines_all rctla2
                      where nge.customer_no = hcaa.account_number
                      and   hcaa.cust_account_id = rcta2.bill_to_customer_id
                      and   rcta2.customer_trx_id = rctla2.customer_trx_id
                    ) npe,                                      --created inline view for npe
                    --nfpc.nfpc_gpm_expense npe,                --commented
                    hz_cust_accounts hca
              WHERE rcta.complete_flag = 'Y'
                AND rcta.interface_header_attribute1 NOT LIKE '%B'
                AND rcta.interface_header_context = 'ORDER ENTRY'
                AND rcta.batch_source_id IN (1068, 1069)
                AND rcta.customer_trx_id = rctla.customer_trx_id
                AND rctla.inventory_item_id = msi.inventory_item_id
                AND UPPER (cct.cost_type) = 'FROZEN'
                AND cic.cost_type_id = cct.cost_type_id
                AND cic.inventory_item_id = msi.inventory_item_id
                --AND npe.customer_no = hca.account_number        --commented
                AND hca.cust_account_id = rcta.bill_to_customer_id
                AND rcta.trx_date BETWEEN '01-FEB-10' AND '01-FEB-10'
                AND rctla.inventory_item_id = npe.inventory_item_id(+)
                AND rctla.customer_trx_line_id = npe.customer_trx_line_id(+)
                AND rctla.customer_trx_id = '903670';Regards
    Imran

  • Datawindow graphical syntax outer join BUG

    Ok, so this is a bug report.  I don't know where i'm supposed to post it for SAP (i do have support).
    The outer join syntax is ansi.
    Using the graphical SQL designer, outer joins are incorrectly written by powerbuilder.  This has been going on ever since ANSI style outer join sytax was added (PB 9?).
    I think it has to do with the datawindow's use of both right and outer joins and its lack of use of inner joins.  The end result is that we have to rewrite a lot of stuff in sql since powerbuilder is generating bad sql.
    The typical example is the use of 2 or more outer joins where the joins are being done using 2 or more columns.
    PB will create both a LEFT and a RIGHT outer join by duplicating the table name.  The table (receive) is only selected ONCE in the sql graphical designer.
    And this is the result:
    Microsoft SQL Native Client
    The objects "receive" and "receive" in the FROM clause have the same exposed names. Use correlation names to distinguish them.
    Do you want to correct errors?
    I would love to see the datawindow sql corrected and written in a more standard way.
    1 change the OUTER JOIN syntax in the db profile setup to indicate the syntax.  not outer join, but syntax.  If you select ANSI have it write ALL joins using JOIN ( from ta join tb on ta.col = tb.col) intead of from tablea, tableb where tablea.col = tableb.col
    2 - eliminate the use of right outer joins.
    At that point i believe that the datawindow could more easily be fixed by SAP to not duplicate tables when in generates the syntax.

    If you have an Oracle Support agreement you can log a Service Request with Oracle, but they may respond that it is not really a bug. The problem is that the "outer" keyword in your 3rd example is being treated as an alias for TABLE_A because it is not considered a reserved keyword.
    with table_a as (
    select 1 as id, 'abc' as value_a from dual union all
    select 2 as id, 'def' as value_a from dual union all
    select 3 as id, 'ghi' as value_a from dual
    , table_b as (
    select 2 as id, 'jkl' as value_b from dual union all
    select 3 as id, 'mno' as value_b from dual union all
    select 4 as id, 'pqr' as value_b from dual
    select ID, outer.VALUE_A, VALUE_B from TABLE_A outer join TABLE_B using (ID);
    ID                     VALUE_A VALUE_B
    2                      def     jkl
    3                      ghi     mnoIf you query the V$RESERVED_WORDS view it will tell you which keywords are reserved.
    select * from V$RESERVED_WORDS where keyword in ('OUTER', 'SELECT','USING');
    KEYWORD                        LENGTH                 RESERVED RES_TYPE RES_ATTR RES_SEMI DUPLICATE
    USING                          5                      N        N        N        N        N
    OUTER                          5                      N        N        N        N        N
    SELECT                         6                      Y        N        N        N        NYou would get a similar result if you tried
    select ID, VALUE_A, VALUE_B from TABLE_A using join TABLE_B using (ID);Regards,
    Bob

  • How to avoid duplicated rows using the outer join

    Hi everybody,
    I have the following query:
    select a.usr_login, b.ugp_rolename, b.ugp_display_name from
    (select usr.usr_login, usr.usr_key, usg.ugp_key from usr,usg
    where usg.usr_key = usr.usr_key
    and usr.usr_login IN ('C01015','C01208')) a,
    (select ugp.ugp_key, ugp.ugp_display_name from ugp
    where ugp.ugp_rolename LIKE 'B-%') b
    where a.ugp_key = b.ugp_key (+)
    The first query 'a' has the following result:
    usr_login <space> usr_key <space> ugp_key
    C01015 <space> 49 <space> 565
    C01015 <space> 49 <space> 683
    C01015 <space> 49 <space> 685
    C01015 <space> 49 <space> 3
    C01208 <space> 257 <space> 3
    The usr_login on table usr is the primary key, and as you can see above, for each usr_login I can find one ore more ugp_key on the table usg.
    The query 'b' gives the list of all the usr_login's roles which have the name LIKE 'B-%' (it means '*Business Roles*'), and all the respective role's key (ugp_key)
    So, when I join the query 'a' with the query 'b', I expect to find for every usr_login the respective ugp_display_name (the Business Role name).
    Because the query 'b' contains ONLY the ugp_keys of the Business Roles, when I execute the complete query, this is the result:
    usr_login <space> ugp_rolename <space> ugp_display_name
    C01015 <space> BK005 <space> TELLER 1
    C01015 <space> BK003 <space> TELLER 2
    C01015 <space> null <space> null
    C01015 <space> null <space> null
    C01208 <space> null <space> null
    As you can see, with the outer join I obtain the Business Name (ugp_display_name) for each occurrence (and I have 2 rows duplicated with 'null' for the usr_login C01015); This beacuse the query 'b' doesn't have the two ugp_keys 685 and 3.
    Instead I'd like to have the following result:
    usr_login <space> ugp_rolename <space> ugp_display_name
    C01015 <space> BK005 <space> TELLER 1
    C01015 <space> BK003 <space> TELLER 2
    C01208 <space> null <space> null
    deleting ONLY the duplicated rows with null, when the usr_login has already at least one ugp_display_name not null.
    For example:
    1) The usr_login 'C01015' has 2 Business Roles (with ugp_key = 565 and 683) and other 2 not-Business Roles (with ugp_key = 685 and 3) --> I want to see ONLY the 2 records related to the Business Roles
    2) The usr_login 'C01208' has only one not-Business Roles (with ugp_key = 3) --> I want to see the record related to the not- Business Role
    Practically:
    1) When a usr_login has one or more Business Roles and other not-Business Roles , I'd like to see ONLY the records about the Business Roles (not the records with 'null','null')
    2) When a usr_login doesn't have Business Roles, I'd like to see the records about the same usr_login with 'null','null'
    This, because I need to show both usr_logins: with and without Business Roles.
    Anybody has any suggestions ? Any help will be appreciated.
    Thanks in advance for any help !!
    Alex

    Hi, Alex,
    So you want to display rows from a where either
    (1) the row has a match in b, or
    (2) no iwith the same usr_login has a match.
    Here's one way to do that:
    WITH     a     AS
         SELECT  usr.usr_login, usr.usr_key, usg.ugp_key
         FROM      usr
         ,     usg
         WHERE      usg.usr_key     = usr.usr_key
         AND     usr.usr_login     IN ('C01015','C01208')
    ,     b     AS
         SELECT  ugp.ugp_key, ugp.ugp_display_name
         FROM      ugp
         WHERE     ugp.ugp_rolename     LIKE 'B-%'
    ,     got_match_cnt     AS
         SELECT     a.usr_login, b.ugp_rolename, b.ugp_display_name
         ,     b.ugp_key
         ,     COUNT (b.ugp_key) OVER (PARTITION BY  a.usr_login)     AS match_cnt
         FROM      a
         ,     b
         WHERE     a.ugp_key     = b.ugp_key (+)
    SELECT     usr_login, ugp_rolename, ugp_display_name
    FROM     got_match_cnt
    WHERE     ugp_key          IS NOT NULL     -- Condition (1)
    OR     match_cnt     = 0              -- Condition (2)
    ;If b.ugp_rolename or b.ugp_display_name can not be NULL, then you could use that just as well as b.ugp_key for testing condition (1).
    By the way, you don't need sub-queries for a and b; you can do all the joins and all the filtering (except conditions (1) and (2)) in one query, but the sub-queries aren't hurting anything. If you find the separate sub-queries easier to understand, debug and maintain, then, by all means, keep them.
    I hope this answers your question.
    If not, post a little sample data (CREATE TABLE and INSERT statements, relevant columns only) for all tables, and also post the results you want from that data.
    Explain, using specific examples, how you get those results from that data.
    Always say which version of Oracle you're using.

  • Creating WHERE clause for an outer join using DatabaseFilter

    Hi all,
    I read a post on thie group about constructing the WHERE clause for a RowSet Controls
    SQL Query using the DatabaseFilter and this is what it said:
    ****************************************************************************The
    following example shows adding part of a WHERE clause in an action method of a
    page flow:
    DatabaseFilter.FilterTerm term = new DatabaseFilter.FilterTerm(); term.sColumnName
    = "name"; term.op = DatabaseFilter.opContains; // there are ops for equals, less
    than, etc... term.value = form.getPartialName();
    // You can also add sort terms for an ORDER BY clause allNames = dbControl.getNames(new
    DatabaseFilter(new DatabaseFilter.FilterTerm[] {term}, null));
    I am trying to create a where clause which uses a join like this:
    Select * from x,y where x.id=y.id (+)
    ie. All values from x.id but only corrosponding ones from y.id.
    Is there any way to build this outer join query using the DatabaseFilter class
    or am i forced to use a String which is contruct in my page flow as the where
    clause?like so:
    * @jc:sql command-type="grid"
    * rowset-name="RFPSRowSet"
    * max-rows="1000"
    * statement::
    * SELECT RFPS.RFP_ID,RFPS.NAME AS RFP_NAME,RFPS.FFO_NUMBER,RFPS.RFP_TYPE,RFPS.CFDA_NUMBER,COMPETITIONS.NAME
    AS COMP_NAME,COMPETITIONS.COMPETITION_ID FROM RFPS,COMPETITIONS WHERE {sql: whereClause
    } {sql: filter.getOrderByClause ()}
    public RowSet getAllRfps(java.lang.String whereClause,DatabaseFilter filter)
    throws SQLException;
    and in my pageFlow action, i do the following:
    StringBuffer whereClause= new StringBuffer();
    whereClause.append("RFPS.RFP_ID = COMPETITIONS.RFP_ID (+)");
    if ((form.getRfpTitle() != null) &&
    (!form.getRfpTitle().equalsIgnoreCase("")))
    whereClause.append(" AND UPPER(RFPS.NAME) LIKE %"+form.getRfpTitle().toUpperCase());
    if ((form.getCfdaNumber() != null) &&
    (!form.getCfdaNumber().equalsIgnoreCase("")))
    whereClause.append(" AND RFPS.CFDA_NUMBER ="+form.getCfdaNumber());
    if ((form.getFfoNumber() != null) &&
    (!form.getFfoNumber().equalsIgnoreCase("")))
    whereClause.append(" AND RFPS.FFO_NUMBER ="+form.getFfoNumber());
    sortFilterService = SortFilterService.getInstance(getRequest());
    DatabaseFilter filter=sortFilterService.getDatabaseFilter(getGridName());
    log.debug("***********"+whereClause.toString()+"***********");
    allRows = searchRfaAndComp.getAllRfps(whereClause.toString(),filter);
    Thanks in advance for your help,
    Regards,
    Vik.

    Thanks for your reply. Just one more question....if we indeed are trying to use
    a simple query and have a where clause like "select * from x where upper(x) like
    {x}", how do we set the UPPER filter on the column using the database filter?
    I see a IDENTIFIER.ISUPPER static field on that DatabaseFilter but am unsure how
    to use it. Would appreciate any pointers .
    Thanks again,
    Vik
    Eddie O'Neil <[email protected]> wrote:
    Vik--
    I believe that the approach that you describe below is the best one
    for dealing with outer joins
    with the DatabaseFilter.
    Apologies for the limitation...
    Eddie
    vik wrote:
    Hi all,
    I read a post on thie group about constructing the WHERE clause fora RowSet Controls
    SQL Query using the DatabaseFilter and this is what it said:
    ****************************************************************************The
    following example shows adding part of a WHERE clause in an actionmethod of a
    page flow:
    DatabaseFilter.FilterTerm term = new DatabaseFilter.FilterTerm(); term.sColumnName
    = "name"; term.op = DatabaseFilter.opContains; // there are ops forequals, less
    than, etc... term.value = form.getPartialName();
    // You can also add sort terms for an ORDER BY clause allNames = dbControl.getNames(new
    DatabaseFilter(new DatabaseFilter.FilterTerm[] {term}, null));
    I am trying to create a where clause which uses a join like this:
    Select * from x,y where x.id=y.id (+)
    ie. All values from x.id but only corrosponding ones from y.id.
    Is there any way to build this outer join query using the DatabaseFilterclass
    or am i forced to use a String which is contruct in my page flow asthe where
    clause?like so:
    * @jc:sql command-type="grid"
    * rowset-name="RFPSRowSet"
    * max-rows="1000"
    * statement::
    * SELECT RFPS.RFP_ID,RFPS.NAME AS RFP_NAME,RFPS.FFO_NUMBER,RFPS.RFP_TYPE,RFPS.CFDA_NUMBER,COMPETITIONS.NAME
    AS COMP_NAME,COMPETITIONS.COMPETITION_ID FROM RFPS,COMPETITIONS WHERE{sql: whereClause
    sql: filter.getOrderByClause ()}* ::
    public RowSet getAllRfps(java.lang.String whereClause,DatabaseFilter
    filter)
    throws SQLException;
    and in my pageFlow action, i do the following:
    StringBuffer whereClause= new StringBuffer();
    whereClause.append("RFPS.RFP_ID = COMPETITIONS.RFP_ID (+)");
    if ((form.getRfpTitle() != null) &&
    (!form.getRfpTitle().equalsIgnoreCase("")))
    whereClause.append(" AND UPPER(RFPS.NAME) LIKE %"+form.getRfpTitle().toUpperCase());
    if ((form.getCfdaNumber() != null) &&
    (!form.getCfdaNumber().equalsIgnoreCase("")))
    whereClause.append(" AND RFPS.CFDA_NUMBER ="+form.getCfdaNumber());
    if ((form.getFfoNumber() != null) &&
    (!form.getFfoNumber().equalsIgnoreCase("")))
    whereClause.append(" AND RFPS.FFO_NUMBER ="+form.getFfoNumber());
    sortFilterService = SortFilterService.getInstance(getRequest());
    DatabaseFilter filter=sortFilterService.getDatabaseFilter(getGridName());
    log.debug("***********"+whereClause.toString()+"***********");
    allRows = searchRfaAndComp.getAllRfps(whereClause.toString(),filter);
    Thanks in advance for your help,
    Regards,
    Vik.

  • Defaulting Null Values in an outer join to the last joined row's values.

    I have a situation where I need to fill in the missing values from an outer join with the last values returned by the join.
    The query is based on a date table, an organization table and a transaction table.
    SELECT D.DATE_ID, O.ORG_ID, T.VALUE
    FROM D_ORGANIZATION O, D_DATE D, F_TRANSACTION T
    WHERE D.DATE_ID = T.DATE_ID(+)
    AND T.ORG_ID = O.ORG_ID(+)
    AND O.ORG_NAME = '&NAME'[
    AND D.THE_DATE >= ADD_MONTHS( TO_DATE( '&&PERIOD_DATE', 'DD-MON-YYYY' ), -23 )
    AND D.THE_DATE <= ADD_MONTHS( TO_DATE( '&&PERIOD_DATE', 'DD-MON-YYYY' ), 24 )
    So the query will return all dates in the 4 year period, and where transactions exist the relevent value.
    DATE_ID ORG_ID VALUE
    38291     2 99.8
    38321     2 45.1
    38352     
    38383     
    38411     
    What I need to happen is:
    DATE_ID ORG_ID VALUE
    38291     2 99.8
    38321     2 45.1
    38352     2 45.1     
    38383 2 45.1
    38411     2 45.1
    Lag appears to be of no use because it will only pick up the last genuine value, so using
    NVL(T.VALUE, LAG(T.VALUE,1) OVER ( .... )
    Gives:
    ATE_ID ORG_ID VALUE
    38291     2 99.8
    38321     2 45.1
    38352     2 45.1     
    38383
    38411     
    The length of the data gap can vary as constituent organisations don't all return their data at the same time, and there may be intermediate dates where no data is returned , but the value needs to be calculated.
    What's going on here is that a gaph is being generated where the tool requires data points to plot the line, once the real data ends a bespoke trend calculations takes over based on the last value returned. I do not have access to the data warehousing options so a solution that doen't need them would be handy, but if not then options can be purchased.
    The tool can't use PL/SQL, but is perhaps a bespoke function in order?

    To do this wouldn't you need to know the data in advance? The real source table had 1800 organisations and 8,000,000 transactions.
    I Tried this as well, creating a pl/sql package as follows.
    create or replace PACKAGE stack AS
    TYPE gnt_push_numbers IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
    TYPE gvt_push_varchars IS TABLE OF VARCHAR(1000) INDEX BY PLS_INTEGER;
    gna_push_numbers gnt_push_numbers;
    gva_push_varchars gvt_push_varchars;
    FUNCTION PUSH ( pn_push_var NUMBER, pn_offset NUMBER) RETURN NUMBER DETERMINISTIC;
    FUNCTION PUSH ( pv_push_var VARCHAR, pn_offset NUMBER) RETURN VARCHAR DETERMINISTIC;
    FUNCTION POP_NUM ( pn_offset NUMBER) RETURN NUMBER DETERMINISTIC;
    FUNCTION POP_VAR ( pn_offset NUMBER) RETURN VARCHAR DETERMINISTIC;
    END stack;
    CREATE OR REPLACE
    PACKAGE BODY "STACK" AS
    FUNCTION push(pn_push_var NUMBER, pn_offset NUMBER) RETURN NUMBER deterministic IS
    BEGIN
    gna_push_numbers(pn_offset) := pn_push_var;
    RETURN pn_push_var;
    END push;
    FUNCTION push(pv_push_var VARCHAR, pn_offset NUMBER) RETURN VARCHAR deterministic IS
    BEGIN
    gva_push_varchars(pn_offset) := pv_push_var;
    RETURN pv_push_var;
    END push;
    FUNCTION pop_num(pn_offset NUMBER) RETURN NUMBER deterministic IS
    BEGIN
    RETURN gna_push_numbers(pn_offset);
    END pop_num;
    FUNCTION pop_var(pn_offset NUMBER) RETURN VARCHAR deterministic IS
    BEGIN
    RETURN gva_push_varchars(pn_offset);
    END pop_var;
    END stack;
    Unfortunately it appears to act before the rows are sorted, so will only work in specialised circumstances, in that you have to ensure the rows have been sorted before the function is used.
    SELECT PUSH(COL), POP..(COL)
    FROM ( SELECT etc.
    Luckily the client decided they didn't want to mix their graphs any more so a more classic approach using a base table select for actuals and then a date table select with a sub-query columns for the projection provided a simple solution.

  • Custom Sort of Duplicated row walues in Webi based on SAP BW Universe

    It is a duplicate thread i have already posted in Integration kits - SAP section.
    This is regarding custom sorting of row value which are duplicated in Webi which is based on SAP BW Universe.
    I have created Webi Report based on Characteristic structure. Using Alerter I provide some space for child node to notify it as child node below a parent node.
    Please see a sample table below:
    AAAA
    onpeak
    midpeak
    offpeak
    BBBB
    onpeak
    midpeak
    offpeak.
    If I enable Avoid duplicate row aggregation, i will be able to see duplicate rows for "onpeak" etc. Since Webi does a default sorting, I have to make a custom sort to replicate the structure followed. And in custom sort i dont see duplicated rows, and i see only one "onpeak". Accordingly if I try to sort using custom sort, then the result will be
    AAAA
    onpeak
    onpeak
    midpeak
    midpeak
    offpeak
    offpeak
    BBBB.
    Please let me know if anyone has any solution for this.
    I have already created report with modifying the row names in backend by adding letter before its value for example "1offpeak" for the duplicated row and then removing the letter "1" in webi using substring. But i know this is the crude way of doing it.

    I have changed the naming convention in BI structure by introducing a white space before the name to avoid duplication and used it in report. Not a good solution anyway.

  • 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

  • View with outer join results wrong number of rows

    Hi,
    When i run a query on a view it returns 2 rows(2 distinct rows), when i run the same query with the select statement which the view is created , it returns only 1 row. According to data the 1 row result is correct, how come twi results. A coding sample as follows. Any help is most appreciated.
    I have a view created based on a outer join of two views in the format;
    create or replace view view1 as
    select ord.order_no order_no,
    ord.del_type del_type,
    det.qty qty
    from detail_view det, order_view ord
    where det.site(+) = ord.site
    and det.part(+) = ord.part
    and nvl(ord.del_type,'_NULL_') <> 'F'
    with read only;
    detail_view & order_view themselves have several group by/sum and union Alls.
    When i run the query on this view
    [Select * from View1 where order_no = 'A30' And del_type = 'B']
    it returns 2 distinct rows. But when i run the select statement which created the View1 with the query it returns only one row!!
    What did i do wrong?
    Thanks
    Sanjeewa

    I cannot reproduce this :
    SCOTT@LSC01> create table detail_view(qty number,site number,part number);
    Table created.
    SCOTT@LSC01> create table order_view(order_no varchar2(10), del_type varchar2(1), site number,part number);
    Table created.
    SCOTT@LSC01>
    SCOTT@LSC01> create or replace view view1 as
      2  select ord.order_no order_no,
      3  ord.del_type del_type,
      4  det.qty qty
      5  from detail_view det, order_view ord
      6  where det.site(+) = ord.site
      7  and det.part(+) = ord.part
      8  and nvl(ord.del_type,'_NULL_') <> 'F'
      9  with read only;
    View created.
    SCOTT@LSC01>
    SCOTT@LSC01> insert into order_view values ('A30','B',1,2);
    1 row created.
    SCOTT@LSC01> insert into order_view values ('A30','B',1,2);
    1 row created.
    SCOTT@LSC01>
    SCOTT@LSC01> Select * from View1 where order_no = 'A30' And del_type = 'B';
    ORDER_NO   D        QTY
    A30        B
    A30        B
    SCOTT@LSC01>
    SCOTT@LSC01> select ord.order_no order_no,
      2  ord.del_type del_type,
      3  det.qty qty
      4  from detail_view det, order_view ord
      5  where det.site(+) = ord.site
      6  and det.part(+) = ord.part
      7  and nvl(ord.del_type,'_NULL_') <> 'F' ;
    ORDER_NO   D        QTY
    A30        B
    A30        Bwhat is your version?

  • Ora-22905:cannot access rows from a non-nested ...(during full outer join)

    Greetings Gurus,
    I'm getting an ORA-22905 when I try and do a full outer join in the following function. If I include the commented lines in the perstren_diff_recs2 function I get the error. Both halfs of the union query work by themselves. When I union them bam error. Also, when I use the full outer join syntax the Oracle session craps the bed with a end of file communication error. That is why I'm using the simulated full outer join.
    My goal was to abstract the XML in my queries. The results from the pipelined function is a delta between what is in the XML document and a relational base table.
    Derrick
    CREATE OR REPLACE PACKAGE XML_UTILS is
    TYPE perstren_typ is record (
    uic varchar2(6),
    tpers varchar2(2),
    deply varchar2(6),
    secur varchar2(1),
    struc number(4),
    auth number(4)
    TYPE perstren_diff_typ is record (
    uic           varchar2(6),
    transaction_type char(1),
    tpers           varchar2(2),
    deply           varchar2(6),
    secur           varchar2(1),
    struc           number(4),
    auth           number(4)
    TYPE perstrenSet is table of perstren_typ;
    TYPE perstrenDiffSet is table of perstren_diff_typ;
    function perstren_recs (uic varchar2) return perstrenSet pipelined;
    function perstren_diff_recs2 (uic varchar2) return perstrenDiffSet pipelined;
    end;
    CREATE OR REPLACE PACKAGE BODY XML_UTILS is
    function perstren_diff_recs2 (uic varchar2) return perstrenDiffSet pipelined is
    cursor perstren_recs_cur(in_uic varchar2) is
    select p.uic, p.tpers, p.deply, P.secur, p.struc,p.auth,
    doc.uic as xmluic,
    doc.tpers as xmltpers,
    doc.deply as xmldeply,
    doc.secur as xmlsecur,
    doc.struc as xmlstruc,
    doc.auth as xmlauth
    from perstren_bac p left outer join
    table(xml_utils.perstren_recs(in_uic)) doc
    on (p.uic = doc.uic and
    p.tpers = doc.tpers and
    p.deply = doc.deply)
    where p.uic = in_uic;
    -- union
    -- select p.uic, p.tpers, p.deply, P.secur, p.struc,p.auth,
    -- doc.uic as xmluic,
    -- doc.tpers as xmltpers,
    -- doc.deply as xmldeply,
    -- doc.secur as xmlsecur,
    -- doc.struc as xmlstruc,
    -- doc.auth as xmlauth
    -- from perstren_bac p right outer join
    -- table(xml_utils.perstren_recs(in_uic)) doc
    -- on (p.uic = doc.uic and
    -- p.tpers = doc.tpers and
    -- p.deply = doc.deply)
    -- where doc.uic = in_uic;
    out_rec perstren_diff_typ;
    begin
    for cur_rec in perstren_recs_cur(uic) loop
    if cur_rec.xmldeply is not null and cur_rec.xmltpers is not null then
    out_rec.uic := cur_rec.xmluic;
    out_rec.tpers := cur_rec.xmltpers;
    out_rec.deply := cur_rec.xmldeply;
    out_rec.secur := cur_rec.xmlsecur;
    out_rec.struc := cur_rec.xmlstruc;
    out_rec.auth := cur_rec.xmlauth;
    else
    out_rec.uic := cur_rec.uic;
    out_rec.tpers := cur_rec.tpers;
    out_rec.deply := cur_rec.deply;
    out_rec.secur := cur_rec.secur;
    out_rec.struc := cur_rec.struc;
    out_rec.auth := cur_rec.auth;
    end if;
    if cur_rec.uic is not null and cur_rec.xmldeply is not null and cur_rec.xmltpers is not null and (
    nvl(cur_rec.secur,'XX') != nvl(cur_rec.xmlsecur,'XX') or
    nvl(cur_rec.struc,9999) != nvl(cur_rec.xmlstruc,9999) or
    nvl(cur_rec.auth,9999) != nvl(cur_rec.xmlauth,9999)) then
    out_rec.transaction_type :='U';
    elsif cur_rec.uic is null and cur_rec.xmldeply is not null then
    out_rec.transaction_type :='I';
    elsif cur_rec.uic is not null and cur_rec.xmldeply is null then
    out_rec.transaction_type :='D';
    else
    out_rec.transaction_type :='O';
    end if;
    PIPE row (out_rec);
    end loop;
    exception
    when others then
    if perstren_recs_cur%isopen then
    close perstren_recs_cur;
    end if;
    raise;
    return;
    end;
    function perstren_recs (uic varchar2) return perstrenSet pipelined is
    cursor perstren_recs_cur(in_uic varchar2) is
    select uic,
    extractvalue(Column_value,'/PERSTREN/TPERS') as TPERS,
    extractvalue(Column_value,'/PERSTREN/DEPLY') as DEPLY,
    extractvalue(Column_value,'/PERSTREN/SECUR') as SECUR,
    extractvalue(Column_value,'/PERSTREN/STRUC') as STRUC,
    extractvalue(Column_value,'/PERSTREN/AUTH') as AUTH
    from test_ref ref,
    table(XMLSequence(extract(ref.XML_DOC,'/RasDataSet/PerstrenList/PERSTREN'))) per
    where ref.uic = in_uic;
    out_rec perstren_typ;
    begin
    open perstren_recs_cur(uic);
    loop
    fetch perstren_recs_cur into out_rec;
    exit when not perstren_recs_cur%FOUND;
    PIPE row (out_rec);
    end loop;
    close perstren_recs_cur;
    exception
    when others then
    if perstren_recs_cur%isopen then
    close perstren_recs_cur;
    end if;
    raise;
    return;
    end;
    end;

    Oracle bug when executing the query in a function

  • Outer Join or Row-Level Function

    Hi ALL,
    I have a query which involves five tables T1, R1, R2, R3 and R4. T1 is a transaction table, whereas R1, R2, R3 and R4 are reference tables (Parent tables, with foreign keys defined in T1). T1 table always contains R1 and R2 referenced data. BUT T1 table may contain sometimes NULL for R3 and R4.
    Now my question is simple;
    Should i use an OUTER Join for R3 and R4 in the query? like
    <code>
    select T1.col1, R1.col2, R2.col2, R3.col2, R4.col2
    from T1, R1, R2, R3, R4
    where T1.col2 = R1.col1
    and T1.col3 = R2.col1
    and T1.col4 = R3.col1(+)
    and T1.col5 = R4.col1(+)
    </code>
    OR
    Should i use row-level functions for R3 and R4, like
    <code>
    select T1.col1, R1.col2, R2.col2,
    (Select R3.col2 from R3 where R3.col1 = T1.col4),
    (Select R4.col2 from R4 where R4.col1 = T1.col5)
    from T1, R1, R2
    where T1.col2 = R1.col1
    and T1.col3 = R2.col1
    </code>
    which approach is better and why?
    Records in T1 = 2,000,000
    Records in R1 = 1000
    Records in R2 = 300
    Records in R3 = 1800
    Records in R4 = 200
    Please note that all foreign keys are indexed, there are primary keys in all R tables
    Thanks,
    QQ.

    dwh_10g wrote:
    I have preferred to go for Outer Joins, as there might be a possibility, if data grows than there will be more row-level scans; hence slower output in future.
    If i go with a row-level scan, then there will be more usage of Hash tables (Memory), so if more memory is required and our SGA limits is crossed, then there will be more disk I/O i guess. which is a costly operation.
    QQ,
    as already explained, unfortunately it's hard to predict how the "row-level" approach is going to perform in case of increased data volume. Since it is dependent on some factors it could be faster or slower than the outer join approach.
    You shouldn't worry too much about the size of the in-memory table. You haven't mentioned your version, but since your alias is "dwh10g" is assume you're using 10g.
    In 10g the size is defined by the hidden parameter "_query_execution_cache_max_size" and set to 65536 bytes by default. In pre-10g the size is always 256 entries which might grow bigger than 64k in case you have large input/output values (e.g. large VARCHAR2 strings). Compared to potentially multiple several megabytes large sort and/or hash SQL work areas used by each open cursor this table seems to be relatively small.
    I don't think that this memory is taken from the SGA, but belongs to the PGA of the process executing the query and therefore it should not allocate SGA memory (I think even in Shared Server configuration this part should be allocated from the PGA of the shared server process).
    So in summary if your data volume increases it shouldn't have an noticeable impact on the memory usage of the "row-level" approach, and therefore this I think is negligible.
    But as a recommendation I would say, since the "row-level" approach doesn't seem to be significantly faster than the "outer join" approach and it's behaviour in future is hard to predict (e.g. it could become worse if your data pattern changes or the execution plan changes and therefore the order of the row processing changes) I would stick to the "outer-join" approach. I assume it could be more stable in terms of performance.
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Unable to collapse rows after full outer joining several tables

    All -
    I often do a "full outer join" on numerous tables when I want to report all of the
    contents of all of the tables in one relatively easy to inspect set of output. However,
    now that my "leading" table is missing certain values, my output is definitely not
    what I want.
    Here's a test case:
    drop table test11;
    create table test11 (x number);
    insert into test11 values (1);
    insert into test11 values (3);
    drop table test12;
    create table test12 (x number);
    insert into test12 values (2);
    insert into test12 values (3);
    drop table test13;
    create table test13 (x number);
    insert into test13 values (1);
    insert into test13 values (2);
    drop table test14;
    create table test14 (x number);
    insert into test14 values (2);
    commit;
    select test11.x t11,
    test12.x t12,
    test13.x t13,
    test14.x t14
    from (((test11 full outer join test12 on test11.x = test12.x)
    full outer join test13 on test11.x = test13.x)
    full outer join test14 on test11.x = test14.x);
    And here is the output:
    T11 T12 T13 T14
    1 1
    3 3
    2
    2
    2
    5 rows selected.
    Forgive me if this doesn't appear with a fixed-width font. I
    don't know how to format these postings.
    See rows 3, 4, and 5? My desire is to jam those
    together so that my output is this instead:
    T11 T12 T13 T14
    1 1
    3 3
    2 2 2
    3 rows selected.
    Do you have any idea how to do this? Of course, I'll need to
    apply the solution to the general case so that all
    test cases similar to this are fixed!
    Thanks very much for your time!
    Tom G.

    For anyone who's interested -
    Here is the solution I was able to put together on my own:
    select max(t11) t11, max(t12) t12, max(t13) t13, max(t14) t14 from
    select coalesce(test11.x, test12.x, test13.x, test14.x) ct,
           test11.x    t11,
           test12.x    t12,
           test13.x    t13,
           test14.x    t14
      from (((test11 full outer join test12 on test11.x = test12.x)
                    full outer join test13 on test11.x = test13.x)
                    full outer join test14 on test11.x = test14.x))
    group by ct;And the output:
           T11        T12        T13        T14
                        2          2          2
             1                     1
             3          3
    3 rows selected.Bye,
    Tom G.

  • Left outer join using date range returns too many rows

    I am trying to pull data for a website.
    Names table:
    company_name varchar2(30)
    julian_day varchar2(3)
    logins number(3)
    login_errors number(3)
    Given a julian date range (e.g. 250-252), I am displaying the information from the Names table.
    The problem is that I also need to display changes (increases/decreases) in the data. I do that by coloring the text based on a 10% increase/decrease. Data for the 3 days 250-252 would be compared to data for the previous 3 days 247-249.
    Not all companies will report data on all days, so some gaps in the data may exist. Therefore, I cannot do just a simple join.
    I am trying to write a query that will give me this information if the user chooses days 250-252.
    Company_name
    sum(logins) for days 250-252
    sum(login_errors) for days 250-252
    sum(logins) for days 247-249
    sum(login_errors) for days 247-249
    The query I'm using is:
    select cur.company_name, sum(cur.logins),
    sum(cur.login_errors), sum(old.logins), sum(old.login_errors)
    FROM names cur LEFT OUTER JOIN names old
    ON cur.company_name = old.company_name
    WHERE cur.adate>='250' and cur.adate<='252'
    and old.adate>='247' and old.adate<='249'
    GROUP by cur.company_name
    Given this data:
    Company_name adate logins login_errors
    ABC 247 10 10
    ABC 248 20 20
    ABC 249 30 30
    ABC 250 15 15
    ABC 251 25 25
    ABC 252 35 35
    My problem is that it returns:
    adate cur.logins cur.login_err old.logins old.login_err
    250 15 15 60 60
    251 25 25 60 60
    252 35 35 60 60
    How can I get it to only give me the one "old" day's data? I went with the LEFT OUTER JOIN because it's possible that there is no data for an "old" day.
    Thanks in advance.....

    Your problem stems from the join itself, and would be the same even without the OUTER JOIN. With your data, there are 3 records in cur and 3 records in old. The join matches each record in cur to each record in old resulting in 9 records in total. Without the SUM, this is clear:
    SQL> SELECT cur.company_name, cur.logins, cur.login_errors,
      2         old.logins, old.login_errors, cur.adate cad, old.adate oad
      3  FROM names cur LEFT OUTER JOIN names old
      4                 ON cur.company_name = old.company_name
      5  WHERE cur.adate>=250 and cur.adate<=252 and
      6        old.adate>=247 and old.adate<=249;
    COMPANY_NA     LOGINS LOGIN_ERRORS     LOGINS LOGIN_ERRORS        CAD        OAD
    ABC                35           35         10           10        252        247
    ABC                25           25         10           10        251        247
    ABC                15           15         10           10        250        247
    ABC                35           35         20           20        252        248
    ABC                25           25         20           20        251        248
    ABC                15           15         20           20        250        248
    ABC                35           35         30           30        252        249
    ABC                25           25         30           30        251        249
    ABC                15           15         30           30        250        249
    9 rows selected.You can do this with only one reference to the table.
    SELECT company_name,
           SUM(CASE WHEN adate BETWEEN 250 and 252 THEN logins ELSE 0 END) curlog,
           SUM(CASE WHEN adate BETWEEN 250 and 252 THEN login_errors ELSE 0 END) curerr,
           SUM(CASE WHEN adate BETWEEN 247 and 249 THEN logins ELSE 0 END) oldlog,
           SUM(CASE WHEN adate BETWEEN 247 and 249 THEN login_errors ELSE 0 END) olderr
    FROM names
    WHERE adate BETWEEN 247 and 252
    GROUP BY company_nameHTH
    John

  • Outer join with first of zero or more rows

    Hi!
    I'm trying to make a join where one part is the first row of zero or more rows. I seem to be getting much poorer performance than I ought to be able to. My tables Node and RelayGroup have 6000 and 3000 rows respectively, while the CommandHist table has 10 million rows. Here are two queries that work, but are fairly slow:
    -- 37s, 28s, 27s
    SELECT DISTINCT n.NodeName,(SELECT Reason from commandhist where CommandHistId = (SELECT MAX(CommandHistID) FROM CommandHist WHERE NodeID = n.NodeID)) AS reason
    FROM RelayGroup rg
    JOIN Node n ON rg.NodeID = n.NodeID
    ORDER BY n.NodeName ASC ;
    -- 21s, 15s, 13s
    SELECT DISTINCT n.NodeName,(MAX(ch.Reason) KEEP (DENSE_RANK FIRST ORDER BY ch.CommandHistID DESC)) AS reason
    FROM RelayGroup rg
    JOIN Node n ON rg.NodeID = n.NodeID
    LEFT OUTER JOIN CommandHist ch ON ch.NodeID = rg.NodeID
    GROUP BY n.NodeName ORDER BY n.NodeName ASC ;
    I suspect that this could be made faster by using ROWNUM to get the first row from CommandHist -- what I'd like to do is
    SELECT n.NodeName, ch.CommandHistID
    FROM Node n
    JOIN RelayGroup rg ON n.NodeID = rg.NodeID
    LEFT OUTER JOIN (SELECT * FROM
    (SELECT CommandHistId, Reason, NodeID FROM CommandHist WHERE NodeID = n.NodeID ORDER BY CommandHistID)
    WHERE ROWNUM = 1) ch ON ch.NodeID = n.NodeID
    ORDER BY n.NodeName ASC;
    except n.NodeID cannot be used within the inner select. Is there a way to 'inject' the value of n.NodeID so that it can be seen from the inner select?
    Thanks in advance,
    -Lars

    Your requirement isn't exactly clear as you haven't provided any table information or example data for us to understand what you are talking about.
    If it's a performance issue take a look at these threads..
    [How to post a SQL tuning request|http://forums.oracle.com/forums/thread.jspa?threadID=863295&tstart=0]
    [When your query takes too long...|http://forums.oracle.com/forums/thread.jspa?messageID=1812597#1812597]

  • How to create a new table based out of old data rows

    Hi All,
    How to create a new table based out of old data rows. Also how can we find out the DBF for different users in a database?
    Saqib

    Not very clear what you need. I'll try to interpret...
    How to create a new table based out of old data rowsIf this means how to create a table from an existing one, then you can do :
    SQL> create table <new table> as select * from <old table>;
    if you need a subset of rows you can add a where clause.
    how can we find out the DBF for different users in a database?Here I need some more clarification. What do you mean exactly ?

Maybe you are looking for