SOLVED!!!Cross DB Link INNER JOIN resultingin 0 rows returned????

Has anyone had experience with a JOIN not returning the result that the data shows it should?
I am writing a query to join two tables across DBs and I know that most of the IDs in the joining columns do in fact match, but when I INNER JOIN, no rows are returned. As you would expect, a LEFT OUTER JOIN RESULTS in my right table showing and a full set of null values for each of the columns of the newly joined table.
Has anyone come across this behavior?
I can even do a select on the table to be joined and use the where clause to show that some of the values from the first table do in fact existed within the table to be joined.
I'm frustrated and a little confused.
Can anyone help?
Message was edited by:
DPotter

Are the columns on which you are joining are of DATE datatype? If yes then without TRUNC you will be in trouble.
If it is not the case give column datatypes and sample data.
See the simple example below:
SQL> SELECT 1 VAL
FROM DUAL
WHERE SYSDATE = TO_DATE('08-MAY-2008','DD-MON-YYYY') ;  2    3 
no rows selected
SQL> SELECT SYSDATE
FROM DUAL;  2 
SYSDATE
08-MAY-08
SQL>
SELECT 1 VAL
FROM DUAL
WHERE TRUNC(SYSDATE) = TO_DATE('08-MAY-2008','DD-MON-YYYY') ;SQL>   2    3 
       VAL
         1

Similar Messages

  • About inner join in abap

    hi
        i am new to sap , i dont no about inner join in abap coding
    plz send me some notes or coding.
                            thank u.
                                                              your regrads
                                                                    divya.

    hi
    use this links
    INNER JOIN  and OUTER JOINhttp://help.sap.com/erp2005_ehp_03/helpdata/EN/cf/21ec77446011d189700000e8322d00/frameset.htm
    JOINED TABLES
    http://help.sap.com/erp2005_ehp_03/helpdata/EN/0f/49bd6a5d5049edba7b3afe6c7956e3/frameset.htm
    u will find all thins related to joins with example and how to use it
    Cheers
    Snehi
    Edited by: snehi chouhan on Jul 25, 2008 9:45 AM

  • Inner joins  Vs  for all entries

    Hi All,
    Pls let me know
    the differences b/w innerjoins and for all entries,,,,which is the best option and  Y??
    Thanks in Advance,
    Bye

    Hi!
    INNER JOIN is used if we want to retrieve some data from more than one table.
    FOR ALL ENTRIES is used if we want some data from a table based on some conditions of some other table.
    Using several nested INNER JOIN statements can be inefficient and cause time out if the tables become too big in the future."
    In ABAP, these joins are first split by the ABAP processor and then sent to the database, with the increase in DATA in production system, these joins tend to give way if your database keeps growing larger and larger.
    You should rather use "FOR ALL ENTRIES IN" (Tabular conditions), which is a much efficient way as far as performance is concerned.
    Check these links:
    inner joins and for all entries
    inner join and for all entries
    Reward points if it helps.
    Regards
    Sudheer

  • Inner Join resulting in many, many duplicates

    I ran an Inner Join but it returned many, many duplicates. Any idea why that would occur?
    One Answer from a different thread:
    Because you may be having improper Join condition what has a One to many or a Many to many relationship between the tables. We do not have the data, and hence cannot comment over it. However, since the original issue is resolved, I suggest you close this thread and ask the question in another thread.
    What do I look for to identify an improper join?

    Please don't start another discussion for the same issue.
    Continue on your existing thread where the answers and advice you've already been given can be seen, so that people don't end up giving the same advice you've already had.
    Answers on other thread: Inner Join error
    Locking this thread

  • Help with Inner join problem

    The following query works fine as long as there is a value in the subID field, which is at the end of the inner join statement. If the subID is blank then no data is output, even though it is there. Try as I may, I can not get the right solution in the where statement to get the data to show without the subID. What am I missing?
    <cfquery name="getInfo" datasource="#application.database#">
    select page_id, pageName, pages.content, pages.cat_id, pages.seo_title,pages.seo_desc,pages.seo_words,pages.h1_title,pages.pic,pages.brochure,pa ges.video,catagories.catagory,subcat.subID,subcat.sub_category
    from (pages INNER JOIN catagories ON pages.cat_id = catagories.cat_id) INNER JOIN subcat ON pages.subID = subcat.subID
    where pages.page_id = #page_id#
    </cfquery>

    Rick,
    Looks like you need a LEFT OUTER join to the "subcat" table, so that all records for "pages" and "catagories" are returned even if no matching "subcat" records exist.  INNER joins will only return selected records when the tables on both sides of the join statement have matching values, while a LEFT OUTER (sometimes also known simply as a LEFT join) join will return *all* selected records from the table(s) on the left side of the join statement regardless of whether there are matching records from the table on the right side of the join statement.  When there are no matching records from the table on the right side of the join statement, any columns in your SELECT clause that are from the table on the right side of the join statement will contain NULLs.
    HTH,
    -Carl V.

  • Need help with inner join and distinct rows

    Hey Guys,
    i have
    1) BaseEnv Table 
    2) Link Table
    3) BaseData Table
    Link table has three columns Id,BaseEnvId,BaseDataId 
    the BaseEnvID is unique in the table where as BaseDataId can be repeated i.e multile rows of BaseEnv Table can point to same BaseData  table row
    Now i want to do  BaseEnvTable inner join Link Table inner join BaseData Table and select 5 columsn ; Name,SyncName,Version,PPO,DOM  from the BaseData table.. the problem is that after i do the inner join I get duplciate records..
    i want to eliminate the duplicate records , can any one help me here

    Please post DDL, so that people do not have to guess what the keys, constraints, Declarative Referential Integrity, data types, etc. in your schema are. Learn how to follow ISO-11179 data element naming conventions and formatting rules. Temporal data should
    use ISO-8601 formats. Code should be in Standard SQL as much as possible and not local dialect. 
    This is minimal polite behavior on SQL forums. Now we have to guess and type, guess and type, etc. because of your bad manners. 
    CREATE TABLE Base_Env
    (base_env_id CHAR(10) NOT NULL PRIMARY KEY,
    Think about the name Base_Data; do you have lots of tables without data? Silly, unh? 
    CREATE TABLE Base_Data
    (base_data_id CHAR(10) NOT NULL PRIMARY KEY,
    Your Links table is wrong in concept and implementation. The term “link” refers to a pointer chain structure used in network databases and makes no sense in RDBMS. There is no generic, magic, universal “id” in RDBMS! People that do this are called “id-iots”
    in SQL slang. 
    We can model a particular relationship in a table by referencing the keys in other tables. But we need to know if the relationship is 1:1, 1:m, or n:m. This is the membership of the relationship. Your narrative implies this: 
    CREATE TABLE Links
    (base_env_id CHAR(10) NOT NULL UNIQUE
       REFERENCES Base_Env (base_env_id),
     base_data_id CHAR(10) NOT NULL
       REFERENCES Base_Data (base_data_id));
    >> The base_env_id is unique in the table where as base_data_id can be repeated I.e multiple rows of Base_Env Table can point [sic] to same Base_Data table row. <<
    Again, RDBMS has no pointers! We have referenced an referencing tables. This is a fundamental concept. 
    That narrative you posted has no ON clauses! And the narrative is also wrong. There is no generic “name”, etc. What tables were used in your non-query? Replace the ?? in this skeleton: 
    SELECT ??.something_name, ??.sync_name, ??.something_version, 
           ??.ppo, ??.dom
    FROM Base_Env AS E, Links AS L, Base_Data AS D
    WHERE ?????????;
    >> I want to eliminate the duplicate records [sic], can any one help me here?<<
    Where is the sample data? Where is the results? Please read a book on RDBMS so you can post correct SQL and try again. 
    --CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking
    in Sets / Trees and Hierarchies in SQL

  • Why is a cross join classified as an inner join?

    hi guys,
    searching the web is just confusing me, so maybe someone here could help.
    On wikipedia (for join) it says:
    An outer join does not require each record in the two joined tables to have a matching record
    Now, a cross join does not require any of the records of the table to have a matching record, therefore I would classify it as an outer join. Why then is it classified as an inner join?
    thanks

    Cross join produces the cross-product. You can not specify cross join condition since there is none - it always implies every row in table1 joined with every row in table2:
    SQL> select ename,dname from emp cross join dept on(1=1)
      2  /
    select ename,dname from emp cross join dept on(1=1)
    ERROR at line 1:
    ORA-00933: SQL command not properly ended
    SQL> With outer join you must specify join condition:
    SQL> select ename,dname from emp left join dept
      2  /
    select ename,dname from emp left join dept
    ERROR at line 1:
    ORA-00905: missing keyword
    SQL> And join result rules are completely different - matching rows or NULL row.
    SY.

  • Link for BUT000 table and ADRC in CRM and inner join is not working in PCUI

    Hi Gurus,
       Please tell me the link btween BUT000 and ADRC table. and i wrote one inner join between BUT000 and BUT0id table but it not working. I m in CRM 4.0 version working with PCUI.
    select but000partner but000name_org1 but000name_org2 but000bus_sort1 but0id~parnter1
          but0ididnumber from but000 inner join but0id on but0idpartner = but000~parnter
    into corresponding fields of table it_result where partner in s_partner.
    It is giving error as partner unknown from but000 table. I delcared everything and tried with alias names also.
    please clarify me.
    regards,
    Ramakrishna.

    Hi Frederic,
       thanks a lot. But is inner join between BUT000 and BUT0ID will work. for me it is not working. plesae see this code.
    tables : but000,
             but0id,
             crmm_but_custno,
             adrc.
    types : begin of typ_but000,
            partner type bu_partner,
            name_org1 type BU_NAMEOR1,
            name_org2 type BU_NAMEOR2,
            bu_sort1  type BU_SORT1,
            idnumber type BU_ID_NUMBER,
            partner1 type bu_partner,
            end of typ_but000.
    data: lt_but000 type table of typ_but000,
          ls_but000 like line of lt_but000.
    *select-options : s_partnr for but000-partner.
    start-of-selection.
          select but000partner but000name_org1 but000name_org2 but000bu_sort1 but0id~parnter1
                    but0id~idnumber into corresponding fields of table lt_but000 from  but000
                    inner join but0id on but0idpartner = but000parnter. " where partner in s_partner.
    it is giving error as but000-partner is not know or but0id-partner not known.
    So, i think if it not works then i should write two select stmts.
    please clarify me.
    i gave u rating.
    thanks
    ramakrishna.

  • Performance considerations between a cross join and inner join

    Hi there,
    What's the performance difference and impact on running a cross-join based query against an inner join based query?
    Regards and thanks

    Before going to the performance issue - ensure you get the required data and not just some data shown.
    Performance should be checked only between equivalent queries which produce same output but with different processing.
    Are you sure you get same output in cross join as well as inner join?
    If so pass on your different queries and then discuss with one is better.

  • How to return all rows with duplicate values? Inner join not working!

    I have a 3 column table:
    location (pk), name, size
    I am attempting to select pairs of entries that have the same
    name and size but different values for location (it is the
    primary key.) My inner join does not seem to return what I need:
    select a.location, a.name, a.size, b.location, b.name, b.size
    from mytable a, mytable b where a.name = b.name and a.size =
    b.size and a.location <> b.location;

    One solution is like this:
    SELECT dname, loc, deptno
    FROM dept
    WHERE (dname, loc) IN
    (SELECT dname, loc
    FROM dept
    GROUP BY dname, loc
    HAVING COUNT (*) > 1
    ORDER BY dname, loc, deptno
    Regards
    Zlatko Sirotic

  • Help with inner join PLEASE IGNORE

    Hi I was doing a select with a subquery but I need that the where clause check to values so I couldn't get it so I decided to create a INNER JOIN
    Before
    insert into BPMTEMP (select * from ODS_VIEWER.BAN_EVENTOS_CONFIRMACION@DBLINK1 where id_solicitud and accion not in (select (id_solicitud, accion) from ODS_VIEWER.BAN_CONFIRMA_RESPUESTA@DBLINK1) and rownum <=200);but the problem with the inner join is that it doesn't accept me the external database source
    insert into BPMTEMP (select ODS_VIEWER.BAN_EVENTOS_CONFIRMACION@DBLINK1.*, ODS_VIEWER.BAN_CONFIRMA_RESPUESTA@DBLINK1.*
    from ODS_VIEWER.BAN_EVENTOS_CONFIRMACION@DBLINK1
    INNER JOIN ODS_VIEWER.BAN_CONFIRMA_RESPUESTA@DBLINK1
    ON [email protected]_solicitud = [email protected]_solicitud
    ON [email protected] = [email protected]
    AND rownum <=200); it shows an:
    ORA-02084:
         database name is missing a component
    Cause:      supplied database name cannot contain a leading '.', trailing '.' or '@', or two '.' or '@' in a row.
    how can I solve this????
    thanks for your help
    Edited by: Diego Guillen on 29/12/2009 11:14 AM

    Hi
    Please remove the @dblink stuff in the column descrptions or use a table alias. This should help.
    drop database link lokal;
    create database link lokal
       CONNECT TO whateveruserineed IDENTIFIED BY whateverthing
       USING 'lokal11g';
    select HR.COUNTRIES.*  from HR.COUNTRIES@lokal;
    select x.* from HR.COUNTRIES@lokal x;And as Dan Morgans says, pls. post you ? in the right forum next time :-))
    Mette

  • Inner join command

    Hi Forum,
    How to use Inner join command?
    Please explain with an example.
    Thanks,
    Mahathi

    Inner Join and Outer Join
    The data that can be selected with a view depends primarily on whether the view implements an inner join or an outer join. With an inner join, you only get the records of the cross-product for which there is an entry in all tables used in the view. With an outer join, records are also selected for which there is no entry in some of the tables used in the view.
    The set of hits determined by an inner join can therefore be a subset of the hits determined with an outer join.
    Database views implement an inner join. The database therefore only provides those records for which there is an entry in all the tables used in the view. Help views and maintenance views, however, implement an outer join.
    Specifying Database Tables
    The FROM clause determines the database tables from which the data specified in the SELECT clause is read. You can specify either a single table or more than one table, linked using inner or outer joins. The names of database tables may be specified statically or dynamically, and you can use alias names. You can also use the FROM clause to bypass the SAP buffer and restrict the number of lines to be read from the database.
    "Database table" can equally mean an ABAP Dictionary view. A view links two or more database tables in the ABAP Dictionary, providing a static join that is available systemwide. You can specify the name of a view wherever the name of a database table may occur in the FROM clause.
    The FROM clause has two parts - one for specifying database tables, and one for other additions:
    SELECT... FROM <tables> <options>...
    In <tables>, you specify the names of database tables and define joins. <options> allows you to specify further additions that control the database access.
    Specifying Database Tables Statically
    To specify the name of a database table statically, use the following:
    SELECT... FROM <dbtab> [AS <alias>] <options> . ..
    The database table <dbtab> must exist in the ABAP Dictionary. The AS addition allows you to specify an alternative name <alias> that you can then use in the SELECT; FROM, WHERE, and GROUP BY clauses. This can eliminate ambiguity when you use more than one database table, especially when you use a single database table more than once in a join. Once you have defined an alias, you may no longer use the real name of the database table
    Specifying Database Tables Dynamically
    To specify the name of a database table dynamically, use the following:
    SELECT... FROM (<name>) <options> . ..
    The field <name> must contain the name of a database table in the ABAP Dictionary. The table name must be written in uppercase. When you specify the name of a database table dynamically, you cannot use an empty INTO clause to read all of the columns into the work area <dbtab>. It is also not possible to use alternative table names.
    Specifying Two or More Database Tables as an Inner Join
    In a relational database, you normally need to read data simultaneously from more than one database table into an application program. You can read from more than one table in a single SELECT statement, such that the data in the tables all has to meet the same conditions, using the following join expression:
    SELECT...
      FROM <tab> [INNER] JOIN <dbtab> [AS <alias>] ON <cond> <options>
    where <dbtab> is a single database table and <tab> is either a table or another join expression. The database tables can be specified statically or dynamically as described above. You may also use aliases. You can enclose each join expression in parentheses. The INNER addition is optional.
    A join expression links each line of <tab> with the lines in <dbtab> that meet the condition <cond>. This means that there is always one or more lines from the right-hand table that is linked to each line from the left-hand table by the join. If <dbtab> does not contain any lines that meet the condition <cond>, the line from <tab> is not included in the selection.
    The syntax of the <cond> condition is like that of the WHERE clause, although individual comparisons can only be linked using AND. Furthermore, each comparison must contain a column from the right-hand table <dbtab>. It does not matter on which side of the comparison it occurs. For the column names in the comparison, you can use the same names that occur in the SELECT clause, to differentiate columns from different database tables that have the same names.
    The comparisons in the condition <cond> can appear in the WHERE clause instead of the ON clause, since both clauses are applied equally to the temporary table containing all of the lines resulting from the join. However, each join must contain at least one comparison in the condition <cond>.
    Specifying Two or More Database Tables as a Left Outer Join
    In an inner join, a line from the left-hand database table or join is only included in the selection if there is one or more lines in the right-hand database table that meet the ON condition <cond>. The left outer join, on the other hand, reads lines from the left-hand database table or join even if there is no corresponding line in the right-hand table.
    SELECT...
      FROM <tab> LEFT [OUTER] JOIN <dbtab> [AS <alias>] ON <cond>
           <options>
    <tab> and <dbtab> are subject to the same rules and conditions as in an inner join. The OUTER addition is optional. The tables are linked in the same way as the inner join with the one exception that all lines selected from <tab> are included in the final selection. If <dbtab> does not contain any lines that meet the condition <cond>, the system includes a single line in the selection whose columns from <dbtab> are filled with null values.
    In the left outer join, more restrictions apply to the condition <cond> than in the inner join. In addition to the above restrictions:
    EQ or = is the only permitted relational operator.
    There must be at least one comparison between columns from <tab> and <dbtab>.
    The WHERE clause may not contain any comparisons with columns from <dbtab>. All comparisons using columns from <dbtab> must appear in the condition <cond>.
    Client Handling
    As already mentioned, you can switch off the automatic client handling in Open SQL statements using a special addition. In the SELECT statement, the addition comes after the options in the FROM clause:
    SELECT... FROM <tables> CLIENT SPECIFIED. ..
    If you use this addition, you can then address the client fields in the individual clauses of the SELECT statement.
    Disabling Data Buffering
    If buffering is allowed for a table in the ABAP Dictionary, the SELECT statement always reads the data from the buffer in the database interface of the current application server. To read data directly from the database table instead of from the buffer, use the following:
    SELECT... FROM <tables> BYPASSING BUFFER. ..
    This addition guarantees that the data you read is the most up to date. However, as a rule, only data that does not change frequently should be buffered, and using the buffer where appropriate improves performance. You should therefore only use this option where really necessary.
    Restricting the Number of Lines
    To restrict the absolute number of lines included in the selection, use the following:
    SELECT... FROM <tables> UP TO <n> ROWS. ..
    If <n> is a positive integer, the system reads a maximum of <n> lines. If <n> is zero, the system reads all lines that meet the selection criteria. If you use the ORDER BY clause as well, the system reads all lines belonging to the selection, sorts them, and then places the first <n> lines in the selection set.
    Examples
    Specifying a database table statically:
    REPORT demo_select_static_database.
    DATA wa TYPE scarr.
    SELECT *
      INTO wa
      FROM scarr UP TO 4 ROWS.
      WRITE: / wa-carrid, wa-carrname.
    ENDSELECT.
    The output is:
    The system reads four lines from the database table SCARR.
    Specifying a database table dynamically:
    REPORT demo_select_dynamic_database.
    DATA wa TYPE scarr.
    DATA name(10) TYPE c VALUE 'SCARR'.
    SELECT  *
      INTO  wa
      FROM  (name) CLIENT SPECIFIED
      WHERE mandt = '000'.
      WRITE: / wa-carrid, wa-carrname.
    ENDSELECT.
    A condition for the MANDT field is allowed, since the example uses the CLIENT SPECIFIED option. If NAME had contained the value ‘scarr’ instead of ‘SCARR’, a runtime error would have occurred.
    Inner join:
    REPORT demo_select_inner_join.
    DATA: BEGIN OF wa,
            carrid TYPE spfli-carrid,
            connid TYPE spfli-connid,
            fldate TYPE sflight-fldate,
            bookid TYPE sbook-bookid,
          END OF wa,
          itab LIKE SORTED TABLE OF wa
                    WITH UNIQUE KEY carrid connid fldate bookid.
    SELECT  pcarrid pconnid ffldate bbookid
      INTO  CORRESPONDING FIELDS OF TABLE itab
      FROM  ( ( spfli AS p
                INNER JOIN sflight AS f ON pcarrid = fcarrid AND
                                           pconnid = fconnid    )
                INNER JOIN sbook   AS b ON bcarrid = fcarrid AND
                                           bconnid = fconnid AND
                                           bfldate = ffldate     )
      WHERE p~cityfrom = 'FRANKFURT' AND
            p~cityto   = 'NEW YORK'  AND
            fseatsmax > fseatsocc.
    LOOP AT itab INTO wa.
      AT NEW fldate.
        WRITE: / wa-carrid, wa-connid, wa-fldate.
    ENDAT.
      WRITE / wa-bookid.
    ENDLOOP.
    This example links the columns CARRID, CONNID, FLDATE, and BOOKID of the table SPFLI, SFLIGHT, and SBOOK, and creates a list of booking numbers for all flights from Frankfurt to New York that are not fully booked. An alias name is assigned to each table.
    Left outer join:
    REPORT demo_select_left_outer_join.
    DATA: BEGIN OF wa,
            carrid   TYPE scarr-carrid,
            carrname TYPE scarr-carrname,
            connid   TYPE spfli-connid,
          END OF wa,
          itab LIKE SORTED TABLE OF wa
                    WITH NON-UNIQUE KEY carrid.
    SELECT scarrid scarrname p~connid
      INTO CORRESPONDING FIELDS OF TABLE itab
      FROM scarr AS s
           LEFT OUTER JOIN spfli AS p ON scarrid   =  pcarrid AND
                                         p~cityfrom = 'FRANKFURT'.
    LOOP AT itab INTO wa.
      WRITE: / wa-carrid, wa-carrname, wa-connid.
    ENDLOOP.
    The output might look like this:
    The example links the columns CARRID, CARRNAME, and CONNID of the tables SCARR and SPFLI using the condition in the left outer join that the airline must fly from Frankfurt. All other airlines have a null value in the CONNID column in the selection.
    If the left outer join is replaced with an inner join, the list looks like this:
    Only lines that fulfill the ON condition are included in the selection.

  • Reply to vj (qery on the inner joins v/s performane test)

    this is ravi shiva's friend.
    hi vj,
             u r working for intelli group....and i had met u twice. by the way give u r contact number i want to speak to u personally.
              here is the code... 
    REPORT  rv_sid_purchase_order_status NO STANDARD PAGE HEADING MESSAGE-ID zrv_message_cl LINE-COUNT 65 LINE-SIZE 110 .
    This include contains declarations
    INCLUDE zrv_sid_purchase_order_t.
    This include contains code for the performs
    INCLUDE zrv_sid_purchase_order_f.
                          Initialization
    INITIALIZATION.
    This perform will initialize the values.
      PERFORM f_initilaize.
    This perform will initialize the field catalog.
      PERFORM f_e01_fieldcat_init USING gt_fieldcat[].
                         Start-Of-Selection
    START-OF-SELECTION.
    This perform will read the values from the database.
      PERFORM f_selection.
    This perform will call the function module to display the values on the list.
      PERFORM f_display.
              End-Of-Selection
    END-OF-SELECTION.
    *&  Include           ZRV_SID_PURCHASE_ORDER_T                         *
               T a b l e s   D e c l a r a t i o n s                     *
    TABLES: ekko,ekpo,ekbe,ekkn,mkpf.
               Type Pools  D e c l a r a t i o n s                       *
    TYPE-POOLS: slis.
          Selection Screen Declaration
    SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-100.
    SELECT-OPTIONS: ebeln FOR ekko-ebeln,
                    aedat FOR ekko-aedat.
    SELECTION-SCREEN END OF BLOCK b1.
               V a r i  a b l e s                                        *
    DATA : gt_fieldcat         TYPE  slis_t_fieldcat_alv,
           g_repid             LIKE  sy-repid,
           gs_keyinfo          TYPE  slis_keyinfo_alv,
           g_tabname_header    TYPE  slis_tabname,
           g_tabname_item      TYPE  slis_tabname,
           ls_layout           TYPE  slis_layout_alv,
           gt_list_top_of_page TYPE  slis_t_listheader.
               I n t e r n a l  T a b l e s                               *
    DATA: BEGIN OF itab OCCURS 0,
           ebeln LIKE ekko-ebeln,
           lifnr LIKE ekko-lifnr,
           aedat LIKE ekko-aedat,
           submi LIKE ekko-submi,
           name1 LIKE lfa1-name1,
           netwr LIKE erev-netwr,
          END OF itab.
    DATA: BEGIN OF jtab OCCURS 0,
           ebeln      LIKE  ekpo-ebeln,
           ebelp      LIKE  ekpo-ebelp,
           aedat      LIKE  ekpo-aedat,
           txz01      LIKE  ekpo-txz01,
           menge1     LIKE  ekpo-menge,
           menge2     LIKE  ekbe-menge,
           effwr1     LIKE  ekpo-effwr,
           mwskz1     LIKE  ekpo-mwskz,
           ps_psp_pnr LIKE  ekkn-ps_psp_pnr,
           bewtp1     LIKE  ekbe-bewtp,
           belnr1     LIKE  ekbe-belnr,
           dmbtt      LIKE  ekbe-dmbtr,
           mblnr1     LIKE  mkpf-mblnr,
           bldat1     LIKE  mkpf-bldat,
           xblnr1     LIKE  mkpf-xblnr,
           frbnr      LIKE  mkpf-frbnr,
          END OF jtab.
    *&  Include           ZRV_SID_PURCHASE_ORDER_F                         *
    FORM f_initilaize .
      g_repid = sy-repid.
      g_tabname_header            = 'itab'.
      g_tabname_item              = 'jtab'.
      CLEAR gs_keyinfo.
      gs_keyinfo-header01         = 'EBELN'.
      gs_keyinfo-item01           = 'EBELN'.
      gs_keyinfo-header02         = space.
      gs_keyinfo-item02           = 'EBELP'.
      ls_layout-group_change_edit = 'X'.
      ls_layout-colwidth_optimize = 'X'.
      ls_layout-zebra             = 'X'.
      ls_layout-detail_popup      = 'X'.
      ls_layout-get_selinfos      = 'X'.
      ls_layout-window_titlebar   = 'PURCHASE ORDER STATUS'.
      ls_layout-no_keyfix         = 'X'.
    ENDFORM.                    " f_INITILAIZE
    *&      Form  f_e01_fieldcat_init
          text
         -->E01_LT_FIELtext
    FORM f_e01_fieldcat_init  USING  e01_lt_fieldcat TYPE slis_t_fieldcat_alv.
      DATA: ls_fieldcat TYPE slis_fieldcat_alv.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'SUBMI'.
      ls_fieldcat-tabname       = g_tabname_header.
      ls_fieldcat-ref_fieldname = 'SUBMI'.
      ls_fieldcat-ref_tabname   = 'EKKO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'EBELN'.
      ls_fieldcat-tabname       = g_tabname_header.
      ls_fieldcat-ref_fieldname = 'EBELN'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'LIFNR'.
      ls_fieldcat-tabname       = g_tabname_header.
      ls_fieldcat-ref_fieldname = 'LIFNR'.
      ls_fieldcat-ref_tabname   = 'EKKO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'NAME1'.
      ls_fieldcat-tabname       = g_tabname_header.
      ls_fieldcat-ref_fieldname = 'NAME1'.
      ls_fieldcat-ref_tabname   = 'LFA1'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'NETWR'.
      ls_fieldcat-tabname       = g_tabname_header.
      ls_fieldcat-ref_fieldname = 'NETWR'.
      ls_fieldcat-ref_tabname   = 'EREV'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-do_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'EBELP'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'EBELP'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'TXZ01'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'TXZ01'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-just = 'L'.
      ls_fieldcat-fieldname     = 'MWSKZ1'.
      ls_fieldcat-seltext_l     = 'Tax code'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'MWSKZ1'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-just          = 'L'.
      ls_fieldcat-fieldname     = 'PS_PSP_PNR'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'PS_PSP_PNR'.
      ls_fieldcat-ref_tabname   = 'EKKN'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'MENGE1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'Po quantity'.
      ls_fieldcat-ref_fieldname = 'MENGE1'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'MENGE1'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'EFFWR1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'Po value'.
      ls_fieldcat-ref_fieldname = 'EFFWR1'.
      ls_fieldcat-ref_tabname   = 'EKPO'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'BEWTP1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'Cat'.
      ls_fieldcat-ref_fieldname = 'BEWTP1'.
      ls_fieldcat-ref_tabname   = 'EKBE'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'BELNR1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'GR/IR MDoc'.
      ls_fieldcat-ref_fieldname = 'BELNR1'.
      ls_fieldcat-ref_tabname   = 'EKBE'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'MENGE2'.
      ls_fieldcat-seltext_l     = 'GR/IR quantity'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'MENGE2'.
      ls_fieldcat-ref_tabname   = 'EKBE'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'MBLNR1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'GR No'.
      ls_fieldcat-ref_fieldname = 'MBLNR1'.
      ls_fieldcat-ref_tabname   = 'MKPF'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'BLDAT1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'GR Date'.
      ls_fieldcat-ref_fieldname = 'BLDAT1'.
      ls_fieldcat-ref_tabname   = 'MKPF'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'FRBNR'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'FRBNR'.
      ls_fieldcat-ref_tabname   = 'MKPF'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'XBLNR1'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-seltext_l     = 'Invoice No in GR'.
      ls_fieldcat-ref_fieldname = 'XBLNR1'.
      ls_fieldcat-ref_tabname   = 'MKPF'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
      CLEAR ls_fieldcat.
      ls_fieldcat-fieldname     = 'DMBTT'.
      ls_fieldcat-seltext_l     = 'Invoice value W/O tax'.
      ls_fieldcat-tabname       = g_tabname_item.
      ls_fieldcat-ref_fieldname = 'DMBTT'.
      ls_fieldcat-ref_tabname   = 'EKBE'.
      ls_fieldcat-key           = 'X'.
      ls_fieldcat-no_out        = 'X'.
      ls_fieldcat-no_sum        = 'X'.
      ls_fieldcat-sp_group      = 'A'.
      APPEND ls_fieldcat TO e01_lt_fieldcat.
    ENDFORM.                    " f_e01_fieldcat_init
    *&      Form  f_selection
          text
    FORM f_selection .
      SELECT   ekko~ebeln
               ekko~lifnr
               ekko~aedat
               ekko~submi
               lfa1~name1
               erev~netwr
                               FROM ekko  INNER JOIN lfa1 ON ( ekkolifnr = lfa1lifnr )
                                          INNER JOIN erev ON ( ekkoebeln = erevedokn )
                                          INTO TABLE itab WHERE ekko~ebeln IN ebeln AND
                                                                ekko~aedat IN aedat AND
                                                                bsart <> 'AN'.
      SELECT
             ekpo~ebeln
             ekpo~ebelp
             ekpo~aedat
             ekpo~txz01
             ekpo~menge
             ekbe~menge
             ekpo~effwr
             ekpo~mwskz
             ekkn~ps_psp_pnr
             ekbe~bewtp
             ekbe~belnr
             ekbe~dmbtr
             mkpf~mblnr
             mkpf~bldat
             mkpf~xblnr
             mkpf~frbnr
                            FROM  ekpo INNER JOIN ekkn      ON ( ekpoebeln = ekknebeln
                                                                           AND
                                                                 ekknebelp = ekpoebelp )
                                       INNER JOIN ekbe      ON ( ekknebeln = ekbeebeln
                                                                           AND
                                                                 ekknebelp = ekbeebelp )
                                       LEFT OUTER JOIN mkpf ON ( ekbebelnr = mkpfmblnr )
                                       INTO TABLE jtab FOR ALL ENTRIES IN itab WHERE ekpo~ebeln = itab-ebeln AND
                                                                                    ekpo~aedat = itab-aedat.
    ENDFORM.                    " f_selection
    *&      Form  f_display
          text
    FORM f_display .
      CALL FUNCTION 'REUSE_ALV_HIERSEQ_LIST_DISPLAY'
        EXPORTING
          i_callback_program = g_repid
          it_fieldcat        = gt_fieldcat[]
          i_tabname_header   = g_tabname_header
          i_tabname_item     = g_tabname_item
          is_keyinfo         = gs_keyinfo
          is_layout          = ls_layout
        TABLES
          t_outtab_header    = itab
          t_outtab_item      = jtab.
    ENDFORM.                    " f_display

    Hi Ravi,
    1. To check performance of a report we use the perfromance trace. The transaction code is ST05.
    You can also refer the link :
         http://help.sap.com/saphelp_erp2005/helpdata/en/8a/3b834014d26f1de10000000a1550b0/content.htm
    2.  Also we can do the run time analysis of the code uising transaction code SE30.
    3. To do a general check on the code , you can use the SAP Code Inspector. The transaction code for this is SCI. This will defentely give you a detailed analysis of the program.
    4 . To have a general idea about the performance tuning of a report , you should refer the link :
       http://www.sapgenie.com/abap/performance.htm.
    Hope this solves yopur query.
    Regards,
    Kunal.

  • Very Slow Query with CTE inner join

    I have 2 tables (heavily simplified here to show relevant columns):
    CREATE TABLE tblCharge
    (ChargeID int NOT NULL,
    ParentChargeID int NULL,
    ChargeName varchar(200) NULL)
    CREATE TABLE tblChargeShare
    (ChargeShareID int NOT NULL,
    ChargeID int NOT NULL,
    TotalAmount money NOT NULL,
    TaxAmount money NULL,
    DiscountAmount money NULL,
    CustomerID int NOT NULL,
    ChargeShareStatusID int NOT NULL)
    I have a very basic View to Join them:
    CREATE VIEW vwBASEChargeShareRelation as
    Select c.ChargeID, ParentChargeID, s.CustomerID, s.TotalAmount, isnull(s.TaxAmount, 0) as TaxAmount, isnull(s.DiscountAmount, 0) as DiscountAmount
    from tblCharge c inner join tblChargeShare s
    on c.ChargeID = s.ChargeID Where s.ChargeShareStatusID < 3
    GO
    I then have a view containing a CTE to get the children of the Parent Charge:
    ALTER VIEW [vwChargeShareSubCharges] AS
    WITH RCTE AS
    SELECT ParentChargeId, ChargeID, 1 AS Lvl, ISNULL(TotalAmount, 0) as TotalAmount, ISNULL(TaxAmount, 0) as TaxAmount,
    ISNULL(DiscountAmount, 0) as DiscountAmount, CustomerID, ChargeID as MasterChargeID
    FROM vwBASEChargeShareRelation Where ParentChargeID is NULL
    UNION ALL
    SELECT rh.ParentChargeID, rh.ChargeID, Lvl+1 AS Lvl, ISNULL(rh.TotalAmount, 0), ISNULL(rh.TaxAmount, 0), ISNULL(rh.DiscountAmount, 0) , rh.CustomerID
    , rc.MasterChargeID
    FROM vwBASEChargeShareRelation rh
    INNER JOIN RCTE rc ON rh.PArentChargeID = rc.ChargeID and rh.CustomerID = rc.CustomerID
    Select MasterChargeID as ChargeID, CustomerID, Sum(TotalAmount) as TotalCharged, Sum(TaxAmount) as TotalTax, Sum(DiscountAmount) as TotalDiscount
    from RCTE
    Group by MasterChargeID, CustomerID
    GO
    So far so good, I can query this view and get the total cost for a line item including all children.
    The problem occurs when I join this table. The query:
    Select t.* from vwChargeShareSubCharges t
    inner join
    tblChargeShare s
    on t.CustomerID = s.CustomerID
    and t.MasterChargeID = s.ChargeID
    Where s.ChargeID = 1291094
    Takes around 30 ms to return a result (tblCharge and Charge Share have around 3.5 million records).
    But the query:
    Select t.* from vwChargeShareSubCharges t
    inner join
    tblChargeShare s
    on t.CustomerID = s.CustomerID
    and t.MasterChargeID = s.ChargeID
    Where InvoiceID = 1045854
    Takes around 2 minutes to return a result - even though the only charge with that InvoiceID is the same charge as the one used in the previous query.
    The same thing occurs if I do the join in the same query that the CTE is defined in.
    I ran the execution plan for each query. The first (fast) query looks like this:
    The second(slow) query looks like this:
    I am at a loss, and my skills at decoding execution plans to resolve this are lacking.
    I have separate indexes on tblCharge.ChargeID, tblCharge.ParentChargeID, tblChargeShare.ChargeID, tblChargeShare.InvoiceID, tblChargeShare.ChargeShareStatusID
    Any ideas? Tested on SQL 2008R2 and SQL 2012

    >> The database is linked [sic] to an established app and the column and table names can't be changed. <<
    Link? That is a term from pointer chains and network databases, not SQL. I will guess that means the app came back in the old pre-RDBMS days and you are screwed. 
    >> I am not too worried about the money field [sic], this is used for money and money based calculations so the precision and rounding are acceptable at this level. <<
    Field is a COBOL concept; columns are totally different. MONEY is how Sybase mimics the PICTURE clause that puts currency signs, commas, period, etc in a COBOL money field. 
    Using more than one operation (multiplication or division) on money columns will produce severe rounding errors. A simple way to visualize money arithmetic is to place a ROUND() function calls after 
    every operation. For example,
    Amount = (Portion / total_amt) * gross_amt
    can be rewritten using money arithmetic as:
    Amount = ROUND(ROUND(Portion/total_amt, 4) * 
    gross_amt, 4)
    Rounding to four decimal places might not seem an 
    issue, until the numbers you are using are greater 
    than 10,000. 
    BEGIN
    DECLARE @gross_amt MONEY,
     @total_amt MONEY,
     @my_part MONEY,
     @money_result MONEY,
     @float_result FLOAT,
     @all_floats FLOAT;
     SET @gross_amt = 55294.72;
     SET @total_amt = 7328.75;
     SET @my_part = 1793.33;
     SET @money_result = (@my_part / @total_amt) * 
    @gross_amt;
     SET @float_result = (@my_part / @total_amt) * 
    @gross_amt;
     SET @Retult3 = (CAST(@my_part AS FLOAT)
     / CAST( @total_amt AS FLOAT))
     * CAST(FLOAT, @gross_amt AS FLOAT);
     SELECT @money_result, @float_result, @all_floats;
    END;
    @money_result = 13525.09 -- incorrect
    @float_result = 13525.0885 -- incorrect
    @all_floats = 13530.5038673171 -- correct, with a -
    5.42 error 
    >> The keys are ChargeID(int, identity) and ChargeShareID(int, identity). <<
    Sorry, but IDENTITY is not relational and cannot be a key by definition. But it sure works just like a record number in your old COBOL file system. 
    >> .. these need to be int so that they are assigned by the database and unique. <<
    No, the data type of a key is not determined by physical storage, but by logical design. IDENTITY is the number of a parking space in a garage; a VIN is how you identify the automobile. 
    >> What would you recommend I use as keys? <<
    I do not know. I have no specs and without that, I cannot pull a Kabbalah number from the hardware. Your magic numbers can identify Squids, Automobile or Lady Gaga! I would ask the accounting department how they identify a charge. 
    >> Charge_Share_Status_ID links [sic] to another table which contains the name, formatting [sic] and other information [sic] or a charge share's status, so it is both an Id and a status. <<
    More pointer chains! Formatting? Unh? In RDBMS, we use a tiered architecture. That means display formatting is in a presentation layer. A properly created table has cohesion – it does one and only one data element. A status is a state of being that applies
    to an entity over a period time (think employment, marriage, etc. status if that is too abstract). 
    An identifier is based on the Law of Identity from formal logic “To be is to be something in particular” or “A is A” informally. There is no entity here! The Charge_Share_Status table should have the encoded values for a status and perhaps a description if
    they are unclear. If the list of values is clear, short and static, then use a CHECK() constraint. 
    On a scale from 1 to 10, what color is your favorite letter of the alphabet? Yes, this is literally that silly and wrong. 
    >> I understand what a CTE is; is there a better way to sum all children for a parent hierarchy? <<
    There are many ways to represent a tree or hierarchy in SQL.  This is called an adjacency list model and it looks like this:
    CREATE TABLE OrgChart 
    (emp_name CHAR(10) NOT NULL PRIMARY KEY, 
     boss_emp_name CHAR(10) REFERENCES OrgChart(emp_name), 
     salary_amt DECIMAL(6,2) DEFAULT 100.00 NOT NULL,
     << horrible cycle constraints >>);
    OrgChart 
    emp_name  boss_emp_name  salary_amt 
    ==============================
    'Albert'    NULL    1000.00
    'Bert'    'Albert'   900.00
    'Chuck'   'Albert'   900.00
    'Donna'   'Chuck'    800.00
    'Eddie'   'Chuck'    700.00
    'Fred'    'Chuck'    600.00
    This approach will wind up with really ugly code -- CTEs hiding recursive procedures, horrible cycle prevention code, etc.  The root of your problem is not knowing that rows are not records, that SQL uses sets and trying to fake pointer chains with some
    vague, magical non-relational "id".  
    This matches the way we did it in old file systems with pointer chains.  Non-RDBMS programmers are comfortable with it because it looks familiar -- it looks like records and not rows.  
    Another way of representing trees is to show them as nested sets. 
    Since SQL is a set oriented language, this is a better model than the usual adjacency list approach you see in most text books. Let us define a simple OrgChart table like this.
    CREATE TABLE OrgChart 
    (emp_name CHAR(10) NOT NULL PRIMARY KEY, 
     lft INTEGER NOT NULL UNIQUE CHECK (lft > 0), 
     rgt INTEGER NOT NULL UNIQUE CHECK (rgt > 1),
      CONSTRAINT order_okay CHECK (lft < rgt));
    OrgChart 
    emp_name         lft rgt 
    ======================
    'Albert'      1   12 
    'Bert'        2    3 
    'Chuck'       4   11 
    'Donna'       5    6 
    'Eddie'       7    8 
    'Fred'        9   10 
    The (lft, rgt) pairs are like tags in a mark-up language, or parens in algebra, BEGIN-END blocks in Algol-family programming languages, etc. -- they bracket a sub-set.  This is a set-oriented approach to trees in a set-oriented language. 
    The organizational chart would look like this as a directed graph:
                Albert (1, 12)
        Bert (2, 3)    Chuck (4, 11)
                       /    |   \
                     /      |     \
                   /        |       \
                 /          |         \
            Donna (5, 6) Eddie (7, 8) Fred (9, 10)
    The adjacency list table is denormalized in several ways. We are modeling both the Personnel and the Organizational chart in one table. But for the sake of saving space, pretend that the names are job titles and that we have another table which describes the
    Personnel that hold those positions.
    Another problem with the adjacency list model is that the boss_emp_name and employee columns are the same kind of thing (i.e. identifiers of personnel), and therefore should be shown in only one column in a normalized table.  To prove that this is not
    normalized, assume that "Chuck" changes his name to "Charles"; you have to change his name in both columns and several places. The defining characteristic of a normalized table is that you have one fact, one place, one time.
    The final problem is that the adjacency list model does not model subordination. Authority flows downhill in a hierarchy, but If I fire Chuck, I disconnect all of his subordinates from Albert. There are situations (i.e. water pipes) where this is true, but
    that is not the expected situation in this case.
    To show a tree as nested sets, replace the nodes with ovals, and then nest subordinate ovals inside each other. The root will be the largest oval and will contain every other node.  The leaf nodes will be the innermost ovals with nothing else inside them
    and the nesting will show the hierarchical relationship. The (lft, rgt) columns (I cannot use the reserved words LEFT and RIGHT in SQL) are what show the nesting. This is like XML, HTML or parentheses. 
    At this point, the boss_emp_name column is both redundant and denormalized, so it can be dropped. Also, note that the tree structure can be kept in one table and all the information about a node can be put in a second table and they can be joined on employee
    number for queries.
    To convert the graph into a nested sets model think of a little worm crawling along the tree. The worm starts at the top, the root, makes a complete trip around the tree. When he comes to a node, he puts a number in the cell on the side that he is visiting
    and increments his counter.  Each node will get two numbers, one of the right side and one for the left. Computer Science majors will recognize this as a modified preorder tree traversal algorithm. Finally, drop the unneeded OrgChart.boss_emp_name column
    which used to represent the edges of a graph.
    This has some predictable results that we can use for building queries.  The root is always (left = 1, right = 2 * (SELECT COUNT(*) FROM TreeTable)); leaf nodes always have (left + 1 = right); subtrees are defined by the BETWEEN predicate; etc. Here are
    two common queries which can be used to build others:
    1. An employee and all their Supervisors, no matter how deep the tree.
     SELECT O2.*
       FROM OrgChart AS O1, OrgChart AS O2
      WHERE O1.lft BETWEEN O2.lft AND O2.rgt
        AND O1.emp_name = :in_emp_name;
    2. The employee and all their subordinates. There is a nice symmetry here.
     SELECT O1.*
       FROM OrgChart AS O1, OrgChart AS O2
      WHERE O1.lft BETWEEN O2.lft AND O2.rgt
        AND O2.emp_name = :in_emp_name;
    3. Add a GROUP BY and aggregate functions to these basic queries and you have hierarchical reports. For example, the total salaries which each employee controls:
     SELECT O2.emp_name, SUM(S1.salary_amt)
       FROM OrgChart AS O1, OrgChart AS O2,
            Salaries AS S1
      WHERE O1.lft BETWEEN O2.lft AND O2.rgt
        AND S1.emp_name = O2.emp_name 
       GROUP BY O2.emp_name;
    4. To find the level and the size of the subtree rooted at each emp_name, so you can print the tree as an indented listing. 
    SELECT O1.emp_name, 
       SUM(CASE WHEN O2.lft BETWEEN O1.lft AND O1.rgt 
       THEN O2.sale_amt ELSE 0.00 END) AS sale_amt_tot,
       SUM(CASE WHEN O2.lft BETWEEN O1.lft AND O1.rgt 
       THEN 1 ELSE 0 END) AS subtree_size,
       SUM(CASE WHEN O1.lft BETWEEN O2.lft AND O2.rgt
       THEN 1 ELSE 0 END) AS lvl
      FROM OrgChart AS O1, OrgChart AS O2
     GROUP BY O1.emp_name;
    5. The nested set model has an implied ordering of siblings which the adjacency list model does not. To insert a new node, G1, under part G.  We can insert one node at a time like this:
    BEGIN ATOMIC
    DECLARE rightmost_spread INTEGER;
    SET rightmost_spread 
        = (SELECT rgt 
             FROM Frammis 
            WHERE part = 'G');
    UPDATE Frammis
       SET lft = CASE WHEN lft > rightmost_spread
                      THEN lft + 2
                      ELSE lft END,
           rgt = CASE WHEN rgt >= rightmost_spread
                      THEN rgt + 2
                      ELSE rgt END
     WHERE rgt >= rightmost_spread;
     INSERT INTO Frammis (part, lft, rgt)
     VALUES ('G1', rightmost_spread, (rightmost_spread + 1));
     COMMIT WORK;
    END;
    The idea is to spread the (lft, rgt) numbers after the youngest child of the parent, G in this case, over by two to make room for the new addition, G1.  This procedure will add the new node to the rightmost child position, which helps to preserve the idea
    of an age order among the siblings.
    6. To convert a nested sets model into an adjacency list model:
    SELECT B.emp_name AS boss_emp_name, E.emp_name
      FROM OrgChart AS E
           LEFT OUTER JOIN
           OrgChart AS B
           ON B.lft
              = (SELECT MAX(lft)
                   FROM OrgChart AS S
                  WHERE E.lft > S.lft
                    AND E.lft < S.rgt);
    7. To find the immediate parent of a node: 
    SELECT MAX(P2.lft), MIN(P2.rgt)
      FROM Personnel AS P1, Personnel AS P2
     WHERE P1.lft BETWEEN P2.lft AND P2.rgt 
       AND P1.emp_name = @my_emp_name;
    I have a book on TREES & HIERARCHIES IN SQL which you can get at Amazon.com right now. It has a lot of other programming idioms for nested sets, like levels, structural comparisons, re-arrangement procedures, etc. 
    --CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking
    in Sets / Trees and Hierarchies in SQL

  • Replacing a inner join with for all entries

    Hi Team,
       In a already developed program I am replacing a inner join with select query follow up with for-all-entris and passing the data to final internal table but in both the case the result should be same then only my replacement will be correct. But my no records in both cases differs. This happening because when i am selecting data from first data base table is 32 lines. then I am doing fo-all-entries moving all the duplicate entries then the no records are four. but in final internal table i am looping the first internal table. So in final internal table the no of records are 32. But in inner join query the records are 16.So please let me know how resolve this issue?
    Thanks and REgards
    Deepa

    Hi Thomas,
      Thanks for ur suggestion.
    The solved that in below.
    In select query I did not change anything The way I had written the code was correct.
    I think many of us know how to write that how to make the performance better in that way.
    I made the change when I transfered the to final internal table.
    The original Inner join code:
    select a~field1 a~field2 a~field3 b~field2 b~field3 b~field4
               from dbtab1 as a  inner join dbtab2 as b
              on a~field1 = b~field1 into it_final where
              a~field1 in s_field1. [Field1  in both the table are key field]
    Before code:
    Sort itab1 by key-fields.
    sort itab2 by keyfields.
    loop at itab1 into wa1.
    move: wa1-field1 to wa_final-field1,
               wa1-field2 to wa_final-field2,
               wa1-field3 to wa_final-field3.
    read table itab2 into wa2 witk key field1 = wa1-field1 binary search.
      if sy-subrc = 0.
      move : wa2-field2 to wa_final-field4,
                 wa2-field3 to wa_final-field5,
                 wa2-field4 to wa_final-field6.
    append wa_final to it_final.
    endif.
    Clear : wa1, wa2, wa_final.
    endloop.
    In this case if the one key fieild value is not present there in second internal table but its there in first internal table still it will read that row with 2nd internal values having zeroes. Normally what does not happen in inner join case if the key field value will same in both the case ,then that will fetch only those rows.
    Changed Code
    loop at itab1 into wa1.
    read table itab2 into wa2 witk key field1 = wa1-field1 binary search.
      if sy-subrc = 0.
    move: wa1-field1 to wa_final-field1,
               wa1-field2 to wa_final-field2,
               wa1-field3 to wa_final-field3.
      move : wa2-field2 to wa_final-field4,
                 wa2-field3 to wa_final-field5,
                 wa2-field4 to wa_final-field6.
    append wa_final to it_final.
    endif.
    Clear : wa1, wa2, wa_final.
    endloop.
    In this case the values will read to final internal table if both key field matches.
    With Regards
    Deepa

Maybe you are looking for

  • Can't view filtered VO properly in a dynamic region

    Hi all, I am using Jdeveloper 11.1.1.0 I have a view object (myVO) that has some view criterias (FilteredVO1, FilteredVO2, ecc.) In myPage I have a dynamic region in which I can view different fragments. These fragments contain filtered data (Filtere

  • Loss of Broadband - 16 days and counting

    Over the past 2 months my broadband has got more unreliable to the point that in the last 16 days it has been virtually unusable. I have a second broadband in to the house that is rock solid with no issues. What seems to happen is that the SN margin

  • Acrobat (and rest of CS 6) stops working due to license problems

    Hi, I just purchased Adobe Creative Suite Standard 6 in Jan 2015. Acrobat works for a 60 day period and then becomes inactive (I don't use other components that often but am assuming those also stop working). The first time I had this happen, I tried

  • Bex query crash for user on sap portal

    hi gurus i have a bex query which users see it through sap portal, i have the case where a user X has made some drill down between rows and columns of the query (over portal), and since then every time this user X open the query, portal shows the que

  • Games on mac

    can i play nfs run or GTA 4 on the mac?