Can this Query be written better?

Dear Experts,
I have this SQL running long, can this be re-written to improve performance. Below is the SQL stmt and its current execution plan:
/* Formatted on 9/12/2012 3:04:16 PM (QP5 v5.163.1008.3004) */
SELECT *
  FROM       SEA_DWSTG.XO_E_PER_ASSIGNMENT_P XO_E_PER_ASSIGNMENT_P
          RIGHT OUTER JOIN
             SEA_DWSTG.X_SNI_FUEL_PUR_TXN_P X_SNI_FUEL_PUR_TXN_P
          ON X_SNI_FUEL_PUR_TXN_P.DRV_NUM = XO_E_PER_ASSIGNMENT_P.DRV_NUM
             AND X_SNI_FUEL_PUR_TXN_P.TXN_DTTM BETWEEN XO_E_PER_ASSIGNMENT_P.ASN_EFF_STRT_DT
                                                   AND XO_E_PER_ASSIGNMENT_P.ASN_EFF_END_DT
             AND XO_E_PER_ASSIGNMENT_P.PS_CURR_IND = 1
             AND XO_E_PER_ASSIGNMENT_P.DRV_NUM IS NOT NULL
             AND XO_E_PER_ASSIGNMENT_P.ACTV_EMP_IND = 1
             AND XO_E_PER_ASSIGNMENT_P.PRSN_TYP_RNK_NUM = 1
       LEFT OUTER JOIN
                SEA_DWSTG.X_SNI_FUEL_PLN_STP_DTL_P X_SNI_FUEL_PLN_STP_DTL_P
             RIGHT OUTER JOIN
                SEA_DWSTG.X_SNI_FUEL_CMPLY_DTL_P X_SNI_FUEL_CMPLY_DTL_P
             ON (X_SNI_FUEL_PLN_STP_DTL_P.PWR_NUM =
                    X_SNI_FUEL_CMPLY_DTL_P.PWR_NUM)
                AND X_SNI_FUEL_PLN_STP_DTL_P.PLN_DTTM =
                       X_SNI_FUEL_CMPLY_DTL_P.PLN_DT
                AND (X_SNI_FUEL_PLN_STP_DTL_P.pln_stp_dtl_id,
                     X_SNI_FUEL_PLN_STP_DTL_P.pwr_num,
                     X_SNI_FUEL_PLN_STP_DTL_P.pln_gal_qty) IN
                       (SELECT pln_stp_dtl_id, pwr_num, pln_gal_qty
                          FROM (SELECT pln_stp_dtl_id,
                                       pwr_num,
                                       pln_gal_qty,
                                       pln_dttm,
                                       ROW_NUMBER ()
                                       OVER (PARTITION BY pwr_num, pln_dttm
                                             ORDER BY pln_stp_dtl_id DESC)
                                          r1
                                  FROM SEA_DWSTG.X_SNI_FUEL_PLN_STP_DTL_P)
                         WHERE r1 = 1)
          LEFT OUTER JOIN
             SEA_DWSTG.X_SNI_TRK_STP_P X_SNI_TRK_STP_P
          ON X_SNI_FUEL_PLN_STP_DTL_P.PRVD_TRK_STP_CD =
                X_SNI_TRK_STP_P.CMDTA_CD
       ON X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID =
             X_SNI_FUEL_CMPLY_DTL_P.FUEL_PUR_TXN_ID,
       SEA_DWSTG.X_SNI_FUEL_PUR_TXN_PRD_P X_SNI_FUEL_PUR_TXN_PRD_P
WHERE (1 = 1)
       AND (X_SNI_FUEL_PUR_TXN_PRD_P.FUEL_PUR_TXN_ID =
               X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID
            AND X_SNI_FUEL_PUR_TXN_PRD_P.PS_CURR_IND = 1
            AND X_SNI_FUEL_PUR_TXN_P.PS_CURR_IND = 1)
PLAN_TABLE_OUTPUT
Plan hash value: 2124177374
| Id  | Operation                         | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
|   0 | SELECT STATEMENT                  |                          |  5909K|    24G|       |    26M  (2)| 98:57:55 |
|*  1 |  HASH JOIN RIGHT OUTER            |                          |  5909K|    24G|   446M|    26M  (2)| 98:57:55 |
|   2 |   VIEW                            |                          |   690K|   438M|       |    25M  (2)| 96:08:32 |
|*  3 |    HASH JOIN OUTER                |                          |   932K|   586M|   232M|    25M  (2)| 96:09:23 |
|   4 |     VIEW                          |                          |   458K|   226M|       |    25M  (2)| 96:08:32 |
|   5 |      NESTED LOOPS OUTER           |                          |   458K|   162M|       |    25M  (2)| 96:08:32 |
|   6 |       TABLE ACCESS FULL           | X_SNI_FUEL_CMPLY_DTL_P   | 30548 |  3430K|       |    46   (3)| 00:00:01 |
|   7 |       VIEW                        |                          |    15 |  3855 |       |   845   (2)| 00:00:12 |
|*  8 |        FILTER                     |                          |       |       |       |            |          |
|*  9 |         HASH JOIN SEMI            |                          |    15 |  1995 |       |   845   (2)| 00:00:12 |
|* 10 |          TABLE ACCESS FULL        | X_SNI_FUEL_PLN_STP_DTL_P |    15 |  1425 |       |   150   (2)| 00:00:03 |
|  11 |          VIEW                     | VW_NSO_1                 |   151K|  5639K|       |   694   (2)| 00:00:10 |
|* 12 |           VIEW                    |                          |   151K|  7569K|       |   694   (2)| 00:00:10 |
|* 13 |            WINDOW SORT PUSHED RANK|                          |   151K|  3413K|  5376K|   694   (2)| 00:00:10 |
|  14 |             TABLE ACCESS FULL     | X_SNI_FUEL_PLN_STP_DTL_P |   151K|  3413K|       |   150   (2)| 00:00:03 |
|  15 |     TABLE ACCESS FULL             | X_SNI_TRK_STP_P          |  5609 |   772K|       |    10   (0)| 00:00:01 |
|* 16 |   HASH JOIN                       |                          |  5909K|    20G|    89M|   409K  (1)| 01:31:27 |
|* 17 |    TABLE ACCESS FULL              | X_SNI_FUEL_PUR_TXN_PRD_P |  1032K|    77M|       |  1011   (4)| 00:00:14 |
|  18 |    VIEW                           |                          |  6959K|    23G|       | 13071   (2)| 00:02:56 |
|* 19 |     HASH JOIN OUTER               |                          |  6959K|  5322M|   179M| 13071   (2)| 00:02:56 |
|* 20 |      TABLE ACCESS FULL            | X_SNI_FUEL_PUR_TXN_P     |  1019K|   168M|       |  2087   (3)| 00:00:28 |
|* 21 |      TABLE ACCESS FULL            | XO_E_PER_ASSIGNMENT_P    |   297K|   178M|       |  5061   (2)| 00:01:08 |
Predicate Information (identified by operation id):
   1 - access("X_SNI_FUEL_PUR_TXN_P"."FUEL_PUR_TXN_ID"="X_SNI_FUEL_CMPLY_DTL_P"."FUEL_PUR_TXN_ID"(+))
   3 - access("X_SNI_FUEL_PLN_STP_DTL_P"."PRVD_TRK_STP_CD"="X_SNI_TRK_STP_P"."CMDTA_CD"(+))
   8 - filter("X_SNI_FUEL_CMPLY_DTL_P"."PLN_DT" IS NOT NULL)
   9 - access("X_SNI_FUEL_PLN_STP_DTL_P"."PLN_STP_DTL_ID"="PLN_STP_DTL_ID" AND
              "X_SNI_FUEL_PLN_STP_DTL_P"."PWR_NUM"="PWR_NUM" AND "X_SNI_FUEL_PLN_STP_DTL_P"."PLN_GAL_QTY"="PLN_GAL_QTY")
  10 - filter("X_SNI_FUEL_PLN_STP_DTL_P"."PWR_NUM"="X_SNI_FUEL_CMPLY_DTL_P"."PWR_NUM" AND
              "X_SNI_FUEL_PLN_STP_DTL_P"."PLN_DTTM"="X_SNI_FUEL_CMPLY_DTL_P"."PLN_DT")
  12 - filter("R1"=1)
  13 - filter(ROW_NUMBER() OVER ( PARTITION BY "PWR_NUM","PLN_DTTM" ORDER BY
              INTERNAL_FUNCTION("PLN_STP_DTL_ID") DESC )<=1)
  16 - access("X_SNI_FUEL_PUR_TXN_PRD_P"."FUEL_PUR_TXN_ID"="from$_subquery$_003"."FUEL_PUR_TXN_ID")
  17 - filter("X_SNI_FUEL_PUR_TXN_PRD_P"."PS_CURR_IND"=1)
  19 - access("X_SNI_FUEL_PUR_TXN_P"."DRV_NUM"="XO_E_PER_ASSIGNMENT_P"."DRV_NUM"(+))
       filter("X_SNI_FUEL_PUR_TXN_P"."TXN_DTTM"<="XO_E_PER_ASSIGNMENT_P"."ASN_EFF_END_DT"(+) AND
              "X_SNI_FUEL_PUR_TXN_P"."TXN_DTTM">="XO_E_PER_ASSIGNMENT_P"."ASN_EFF_STRT_DT"(+))
  20 - filter("X_SNI_FUEL_PUR_TXN_P"."PS_CURR_IND"=1)
  21 - filter("XO_E_PER_ASSIGNMENT_P"."DRV_NUM"(+) IS NOT NULL AND
              "XO_E_PER_ASSIGNMENT_P"."ACTV_EMP_IND"(+)=1 AND "XO_E_PER_ASSIGNMENT_P"."PS_CURR_IND"(+)=1 AND
              "XO_E_PER_ASSIGNMENT_P"."PRSN_TYP_RNK_NUM"(+)=1)
Note
   - SQL plan baseline "SYS_SQL_PLAN_160e8c87962a1dc5" used for this statement
55 rows selected.

Hello
I think you have some issues with your logic here. For example
LEFT OUTER JOIN
  SEA_DWSTG.X_SNI_TRK_STP_P X_SNI_TRK_STP_P
ON X_SNI_FUEL_PLN_STP_DTL_P.PRVD_TRK_STP_CD = X_SNI_TRK_STP_P.CMDTA_CD
ON X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID     = X_SNI_FUEL_CMPLY_DTL_P.FUEL_PUR_TXN_ID,
  SEA_DWSTG.X_SNI_FUEL_PUR_TXN_PRD_P X_SNI_FUEL_PUR_TXN_PRD_P
WHERE (1                                      = 1)
AND (X_SNI_FUEL_PUR_TXN_PRD_P.FUEL_PUR_TXN_ID = X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID
AND X_SNI_FUEL_PUR_TXN_PRD_P.PS_CURR_IND      = 1
AND X_SNI_FUEL_PUR_TXN_P.PS_CURR_IND          = 1)You're using a left outer join but then you're specifying a where clause which means this has to be an inner join. And specifically what is this bit doing...
ON X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID     = X_SNI_FUEL_CMPLY_DTL_P.FUEL_PUR_TXN_ID,
  SEA_DWSTG.X_SNI_FUEL_PUR_TXN_PRD_P X_SNI_FUEL_PUR_TXN_PRD_PYou appear to be mixing ANSI join syntax with oracle style syntax i.e you've got a comma after X_SNI_FUEL_CMPLY_DTL_P.FUEL_PUR_TXN_ID, and then you're specifying another table. Why isn't this using ANSI syntax?
And what's the deal with mixing the left and right outer joins? Try to make it consistent.
You're accessing X_SNI_FUEL_PLN_STP_DTL_P twice but as far as I can tell you could avoid the second access in the subquery by bringing the ROW_NUMBER function into the main select and wrapping it in an inline view to do the filtering.
i.e.
SELECT
FROM
    SELECT  XO_E_PER_ASSIGNMENT_P.*,
            X_SNI_FUEL_PUR_TXN_P.*
            X_SNI_FUEL_PLN_STP_DTL_P.*
            X_SNI_FUEL_CMPLY_DTL_P.*
            X_SNI_TRK_STP_P.*
            X_SNI_FUEL_PUR_TXN_PRD_P.*
            ROW_NUMBER () OVER (PARTITION BY pwr_num, pln_dttm,pln_gal_qty ORDER BY pln_stp_dtl_id DESC) r1
    FROM
      SEA_DWSTG.XO_E_PER_ASSIGNMENT_P XO_E_PER_ASSIGNMENT_P
    RIGHT OUTER JOIN
      SEA_DWSTG.X_SNI_FUEL_PUR_TXN_P X_SNI_FUEL_PUR_TXN_P
      ON X_SNI_FUEL_PUR_TXN_P.DRV_NUM = XO_E_PER_ASSIGNMENT_P.DRV_NUM
      AND X_SNI_FUEL_PUR_TXN_P.TXN_DTTM BETWEEN XO_E_PER_ASSIGNMENT_P.ASN_EFF_STRT_DT AND XO_E_PER_ASSIGNMENT_P.ASN_EFF_END_DT
      AND XO_E_PER_ASSIGNMENT_P.PS_CURR_IND      = 1
      AND XO_E_PER_ASSIGNMENT_P.DRV_NUM         IS NOT NULL
      AND XO_E_PER_ASSIGNMENT_P.ACTV_EMP_IND     = 1
      AND XO_E_PER_ASSIGNMENT_P.PRSN_TYP_RNK_NUM = 1
    LEFT OUTER JOIN
      SEA_DWSTG.X_SNI_FUEL_PLN_STP_DTL_P X_SNI_FUEL_PLN_STP_DTL_P
    RIGHT OUTER JOIN
      SEA_DWSTG.X_SNI_FUEL_CMPLY_DTL_P X_SNI_FUEL_CMPLY_DTL_P
      ON (X_SNI_FUEL_PLN_STP_DTL_P.PWR_NUM = X_SNI_FUEL_CMPLY_DTL_P.PWR_NUM)
      AND X_SNI_FUEL_PLN_STP_DTL_P.PLN_DTTM = X_SNI_FUEL_CMPLY_DTL_P.PLN_DT
      AND (X_SNI_FUEL_PLN_STP_DTL_P.pln_stp_dtl_id, X_SNI_FUEL_PLN_STP_DTL_P.pwr_num, X_SNI_FUEL_PLN_STP_DTL_P.pln_gal_qty)
    LEFT OUTER JOIN
      SEA_DWSTG.X_SNI_TRK_STP_P X_SNI_TRK_STP_P
    ON X_SNI_FUEL_PLN_STP_DTL_P.PRVD_TRK_STP_CD = X_SNI_TRK_STP_P.CMDTA_CD
    ON X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID     = X_SNI_FUEL_CMPLY_DTL_P.FUEL_PUR_TXN_ID, 
    SEA_DWSTG.X_SNI_FUEL_PUR_TXN_PRD_P X_SNI_FUEL_PUR_TXN_PRD_P
    WHERE (1                                      = 1)
    AND (X_SNI_FUEL_PUR_TXN_PRD_P.FUEL_PUR_TXN_ID = X_SNI_FUEL_PUR_TXN_P.FUEL_PUR_TXN_ID
    AND X_SNI_FUEL_PUR_TXN_PRD_P.PS_CURR_IND      = 1
    AND X_SNI_FUEL_PUR_TXN_P.PS_CURR_IND          = 1)
WHERE
    r1 = 1From a performance perspective it's not helping that you're doing full table scans in a nested loop. I think you need to clarify some of your logic and remove the unnecessary outer joins and then you can look to address some of the performance issues.
David

Similar Messages

  • How can this query avoid full table scans?

    It is difficult to avoid full table scans in the following query because the values of column STATUS reiterant numbers. There are only 10 numbers values for the STATUS column (1..10)
    But the table is very large. there are more than 1 million rows in it. A full table scanning consumes too much time.
    How can this query avoid full table scans?
    Thank you
    SELECT SYNC,CUS_ID INTO V_SYNC,V_CUS_ID FROM CONSUMER_MSG_IDX
                      WHERE CUS_ID = V_TYPE_CUS_HEADER.CUS_ID AND
                            ADDRESS_ID = V_TYPE_CUS_HEADER.ADDRESS_ID AND
                            STATUS =! 8;Edited by: junez on Jul 23, 2009 7:30 PM

    Your code had an extra AND. I also replaced the "not equal" operator, which has display problems with the forum software
    SELECT SYNC,CUS_ID
       INTO V_SYNC,V_CUS_ID
      FROM CONSUMER_MSG_IDX
    WHERE CUS_ID = V_TYPE_CUS_HEADER.CUS_ID AND
           ADDRESS_ID = V_TYPE_CUS_HEADER.ADDRESS_ID AND
           STATUS != 8;Are you sure this query is doing a table scan? Is there an index on CUS_ID, ADDRESS_ID? I would think that would be mostly unique. So I'm not sure why you think the STATUS column is causing problems. It would seem to just be a non-selective additional filter.
    Justin

  • Can this query be optimised?

    Hi,
    This query is taking more time to execute. please can someone advise..
    SELECT reference_value AS billing_system_account_id,
    account_id AS sim_account_id
    FROM account_reference
    WHERE reference_name = 'ACCOUNT_ID'
    AND account_id IN
    (SELECT DISTINCT (ACCOUNT_ID)
    FROM asset
    WHERE status NOT IN ('CEASED', 'CANCELLED')
    AND asset_id IN
    (SELECT asset_id
    FROM asset_config
    WHERE config_name IN
    ('userName', 'login')
    AND (config_value IN
    ('abc'
    || '@abc',
    'abc'))))

    Using EXISTS instead of IN, as Salim suggested, might work for you.
    Some more explanation:
    http://asktom.oracle.com/pls/asktom/f?p=100:11:2095243262787694::::P11_QUESTION_ID:953229842074
    But anyway:
    when posting a tuning request, you always need to mention:
    - your database version
    - an execution plan of the query (or tkprof output)
    - information regarding indexes
    - information regarding table statistics
    in order to make it possible for us to help you better.
    Please read these informative threads regarding posting tuning requests:
    When your query takes too long ...
    HOW TO: Post a SQL statement tuning request - template posting

  • Can this query work?

    I'm having trouble with a query because I need the Count results in the query below to refer only to the current column of the SQL Report:
    select T1.id,
    T1.name,
    (select count(*) from T1 where typeid = 222
    AND id = # T1.id#) "COUNT 1",
    (select count(*) from T1 where typeid = 262
    AND id = # T1.id#) "COUNT 2"
    from T1
    order by T1.name
    Is this possible to do? If I substitute an actual ID instead of the #T1.id#, it returns the results that I want.
    Thanks much,
    Nora

    Try this -
    select
      a.id,
      a.name,
      (select count(*) from t1 b where b.typeid = 222 and b.id = a.id) 'COUNT 1',
      (select count(*) from t1 b where b.typeid = 262 and b.id = a.id) 'COUNT 2',
    from
      t1 a
    order by a.nameWithout more details about what you're trying to achieve it's hard to suggest (better) alternatives

  • Can this query statement be made robust.

    select to_char(t1.t_date,'YYYY-MM') as date_used,
                    SUM(t1.much_amount) as amount,
                      t1.p_id as type_id
                        from t1_one
                           where t1.wo_type like 'NEWYORK'
                              and t1.p_id = 'CAR'
                              or t1.p_id = 'BOAT'
                              or t1.p_id = "PLANE'
                              or t1.p_id = 'HORSE'
                              or t1.p_id = 'DOG'
                              or t1.p_id = 'CAT'
                              or t1.p_id = 'PIG'
                              or t1.p_id = 'ELEPHANT'
                              or t1.p_id = 'TIGER'
                              or t1.p_id = 'SNAKE'
                               and trunc(t1.t_date) between to_date('2010'||'-01-01','YYYY-MM-DD') and to_date('2010'||'-12-31', 'YYYY-MM-DD')
                              group by to_char(t1.t_date,'YYYY-MM'), t1.p_id
    {code}
    kindly note in my table, i have the following p_id: CAR, BOAT, PLANE, HORSE, DOG, CAT, PIG, ELEPHANT, TIGER, SNAKE, how though, in the near future, i have a feeling those p_id items could be added on, so i need a way to get all the p_id without hardcoding it like the way i did above. I am still new to oracle and learning everyday. thank you.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

    If you always wanted to limit your query to those 10 names, you could simplify your query a little:
    select to_char(t1.t_date,'YYYY-MM') as date_used
          ,SUM(t1.much_amount) as amount
          ,t1.p_id as type_id
    from   t1_one
    where  t1.wo_type like 'NEWYORK'
    and    t1.p_id IN ('CAR', 'BOAT', 'PLANE', 'HORSE', 'DOG'
                      ,'CAT', 'PIG', 'ELEPHANT', 'TIGER', 'SNAKE')
    and    t1.t_date >= to_date('2010-01-01','YYYY-MM-DD')
    and    t1.t_date <  to_date('2011-01-01','YYYY-MM-DD')
    group  by to_char(t1.t_date,'YYYY-MM'), t1.p_id;If you want to make the query more flexible, store those names in a separate table and use a subquery (or join to it):
    select to_char(t1.t_date,'YYYY-MM') as date_used
          ,SUM(t1.much_amount) as amount
          ,t1.p_id as type_id
    from   t1_one
    where  t1.wo_type like 'NEWYORK'
    and    t1.p_id IN (select x.p_id from some_table x)     ---<<<
    and    t1.t_date >= to_date('2010-01-01','YYYY-MM-DD')
    and    t1.t_date <  to_date('2011-01-01','YYYY-MM-DD')
    group  by to_char(t1.t_date,'YYYY-MM'), t1.p_id;Then you just need to manage the table with the list of names and your query won't need to be changed.

  • Can this be done a better way?

    I have text in three columns in a JTextArea with a Titledborder. The Titledborder is trying to double as column headings as well, not very attractive.
    Anyone have any suggestions on how to improver the gui?
    Below is a link of what the gui looks like.
    Any feedback would be appreciated.
    http://www.astent.plus.com/gui_test/gui1.jpg
    Cheers
    Adrian

    Use a JTable instead. It solves all your column problems.
    //david

  • How can i speedup this query ?

    Hi,
    have a look at this query:
    SELECT DISTINCT element_short_description
               FROM sample_test_report, test_group, test_element_master
              WHERE str_test_group_code = tgr_test_group_code
                AND str_element_code = element_code
                AND tgr_group_description = 'SINTER_CHEMICAL_ANALYSIS'
           ORDER BY element_short_descriptionThing is that total number of rows present in "sample_test_report" tables are in lakh ...around 50 lakh.Other two tables have a few rows. This query is taking around 15 seconds for completion, can this query be made faster ?
    Note that proper indexing have been done already.
    Thanks.

    SELECT DISTINCT element_short_description
    FROM sample_test_report, test_group, test_element_master
    WHERE str_test_group_code = tgr_test_group_code
    AND str_element_code = element_code
    AND tgr_group_description = 'SINTER_CHEMICAL_ANALYSIS'
    ORDER BY element_short_description
    Can you provide us with explain plan?
    I suggest you use table alias every time:
    The alias is specified in the FROM clause after each table name.
    Table aliases make your queries more readable.
    Then gather statistics your tables:
    BEGIN
    DBMS_STATS.GATHER_TABLE_STATS('OWNER','TABLE',estimate_percent=>NULL,method_opt=>'FOR ALL INDEXED COLUMNS SIZE AUTO',DEGREE=>10,CASCADE=>TRUE,granularity=>'ALL');
    END;
    if your db version < 10g
    ANALYZE TABLE employees COMPUTE STATISTICS;
    ANALYZE TABLE employees ESTIMATE STATISTICS;
    If necessary rebuild index, check indexes are use.
    Unusable indexes are made valid by rebuilding them to recalculate the pointers.
    Rebuilding an unusable index re-creates the index in a new location, and then drops the unusable index. This can be done either by using Enterprise Manager or through SQL commands:
    ALTER INDEX HR.emp_empid_pk REBUILD;
    ALTER INDEX HR.emp_empid_pk REBUILD ONLINE;
    ALTER INDEX HR.email REBUILD TABLESPACE USERS;
    Note: Rebuilding an index requires that free space be available for the rebuild. Verify that there is sufficient space before attempting the rebuild. Enterprise Manager checks space requirements automatically.
    At the end, try join table separately and then concatenate them.
    Your query will be work good.
    Look at execution plan, if indexes are not used, use HINTs : There are many Oracle hints available to the developer for use in tuning SQL statements that are embedded in PL/SQL.
    please refer to http://www.dba-oracle.com/t_sql_hints_tuning.htm and http://www.adp-gmbh.ch/ora/sql/hints/index.html
    Good luck

  • How to update this query and avoid performance issue?

    Hi, guys:
    I wonder how to update the following query to make it weekend day aware. My boss want the query to consider business days only. Below is just a portion of the query:
    select count(distinct cmv.invoicekey ) total ,'3' as type, 'VALID CALL DATE' as Category
    FROM cbwp_mv2 cmv
    where cmv.colresponse=1
    And Trunc(cmv.Invdate)  Between (Trunc(Sysdate)-1)-39 And (Trunc(Sysdate)-1)-37
    And Trunc(cmv.Whendate) Between cmv.Invdate+37 And cmv.Invdate+39the CBWP_MV2 is a materialized view to tune query. This query is written for a data warehouse application, the CBWP_MV2 will be updated every day evening. My boss wants the condition in the query to consider only business days, for example, if (Trunc(Sysdate)-1)-39 falls in weekend, I need to move the range begins from next coming business day, if (Trunc(Sysdate)-1)-37 falls in weekend, I need to move the range ends from next coming business day. but I should always keep the range within 3 business days. If there is overlap on weekend, always push to later business days.
    Question: how to implement it and avoid performance issue? I am afraid that if I use a function, it greatly reduce the performance. This view already contains more than 100K rows.
    thank you in advance!
    Sam
    Edited by: lxiscas on Dec 18, 2012 7:55 AM
    Edited by: lxiscas on Dec 18, 2012 7:56 AM

    You are already using a function, since you're using TRUNC on invdate and whendate.
    If you have indexes on those columns, then they will not be used because of the TRUNC.
    Consider omitting the TRUNC or testing with Function Based Indexes.
    Regarding business days:
    If you search this forum, you'll find lots of examples.
    Here's another 'golden oldie': http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:185012348071
    Regarding performance:
    Steps to take are explained from the links you find here: {message:id=9360003}
    Read them, they are more than worth it for now and future questions.

  • How can we rewrite this query for better performance

    Hi All,
    The below query is taking more time to run. Any ideas how to improve the performance by rewriting the query using NOT EXITS or any other way...
    Help Appreciated.
    /* Formatted on 2012/04/25 18:00 (Formatter Plus v4.8.8) */
    SELECT vendor_id
    FROM po_vendors
    WHERE end_date_active IS NULL
    AND enabled_flag = 'Y'
    and vendor_id NOT IN ( /* Formatted on 2012/04/25 18:25 (Formatter Plus v4.8.8) */
    SELECT vendor_id
    FROM po_headers_all
    WHERE TO_DATE (creation_date) BETWEEN TO_DATE (SYSDATE - 365)
    AND TO_DATE (SYSDATE))
    Thanks

    Try this one :
    This will help you for partial fetching of data
    SELECT /*+ first_rows(50) no_cpu_costing */
    vendor_id
    FROM po_vendors
    WHERE end_date_active IS NULL
    AND enabled_flag = 'Y'
    AND vendor_id NOT IN (
    SELECT vendor_id
    FROM po_headers_all
    WHERE TO_DATE (creation_date) BETWEEN TO_DATE (SYSDATE - 365)
    AND TO_DATE (SYSDATE))
    overall your query is also fine, because, the in this query the subquery always contain less data compare to main query.

  • How I can change this query, so I can display the name and scores in one r

    How I can change this query, so I can add the ID from the table SPRIDEN
    as of now is giving me what I want:
    1,543     A05     24     A01     24     BAC     24     BAE     24     A02     20     BAM     20in one line but I would like to add the id and name that are stored in the table SPRIDEN
    SELECT sortest_pidm,
           max(decode(rn,1,sortest_tesc_code)) tesc_code1,
           max(decode(rn,1,score)) score1,
           max(decode(rn,2,sortest_tesc_code)) tesc_code2,
           max(decode(rn,2,score)) score2,
           max(decode(rn,3,sortest_tesc_code)) tesc_code3,
           max(decode(rn,3,score))  score3,
           max(decode(rn,4,sortest_tesc_code)) tesc_code4,
           max(decode(rn,4,score))  score4,
           max(decode(rn,5,sortest_tesc_code)) tesc_code5,
           max(decode(rn,5,score))  score5,
           max(decode(rn,6,sortest_tesc_code)) tesc_code6,
           max(decode(rn,6,score))  score6        
      FROM (select sortest_pidm,
                   sortest_tesc_code,
                   score,
                  row_number() over (partition by sortest_pidm order by score desc) rn
              FROM (select sortest_pidm,
                           sortest_tesc_code,
                           max(sortest_test_score) score
                      from sortest,SPRIDEN
                      where
                      SPRIDEN_pidm =SORTEST_PIDM
                    AND   sortest_tesc_code in ('A01','BAE','A02','BAM','A05','BAC')
                     and  sortest_pidm is not null 
                    GROUP BY sortest_pidm, sortest_tesc_code))
                    GROUP BY sortest_pidm;
                   

    Hi,
    That depends on whether spriden_pidm is unique, and on what you want for results.
    Whenever you have a problem, post a little sample data (CREATE TABLE and INSERT statements, relevamnt columns only) for all tables, and the results you want from that data.
    If you can illustrate your problem using commonly available tables (such as those in the scott or hr schemas) then you don't have to post any sample data; just post the results you want.
    Either way, explain how you get those results from that data.
    Always say which version of Oracle you're using.
    It looks like you're doing something similiar to the following.
    Using the emp and dept tables in the scott schema, produce one row of output per department showing the highest salary in each job, for a given set of jobs:
    DEPTNO DNAME          LOC           JOB_1   SAL_1 JOB_2   SAL_2 JOB_3   SAL_3
        20 RESEARCH       DALLAS        ANALYST  3000 MANAGER  2975 CLERK    1100
        10 ACCOUNTING     NEW YORK      MANAGER  2450 CLERK    1300
        30 SALES          CHICAGO       MANAGER  2850 CLERK     950On each row, the jobs are listed in order by the highest salary.
    This seems to be analagous to what you're doing. The roles played by sortest_pidm, sortest_tesc_code and sortest_test_score in your sortest table are played by deptno, job and sal in the emp table. The roles played by spriden_pidm, id and name in your spriden table are played by deptno, dname and loc in the dept table.
    It sounds like you already have something like the query below, that produces the correct output, except that it does not include the dname and loc columns from the dept table.
    SELECT    deptno
    ,       MAX (DECODE (rn, 1, job))     AS job_1
    ,       MAX (DECODE (rn, 1, max_sal))     AS sal_1
    ,       MAX (DECODE (rn, 2, job))     AS job_2
    ,       MAX (DECODE (rn, 2, max_sal))     AS sal_2
    ,       MAX (DECODE (rn, 3, job))     AS job_3
    ,       MAX (DECODE (rn, 3, max_sal))     AS sal_3
    FROM       (
               SELECT    deptno
               ,          job
               ,          max_sal
               ,          ROW_NUMBER () OVER ( PARTITION BY  deptno
                                              ORDER BY          max_sal     DESC
                                )         AS rn
               FROM     (
                             SELECT    e.deptno
                       ,           e.job
                       ,           MAX (e.sal)     AS max_sal
                       FROM      scott.emp        e
                       ,           scott.dept   d
                       WHERE     e.deptno        = d.deptno
                       AND           e.job        IN ('ANALYST', 'CLERK', 'MANAGER')
                       GROUP BY  e.deptno
                       ,           e.job
    GROUP BY  deptno
    ;Since dept.deptno is unique, there will only be one dname and one loc for each deptno, so we can change the query by replacing "deptno" with "deptno, dname, loc" throughout the query (except in the join condition, of course):
    SELECT    deptno, dname, loc                    -- Changed
    ,       MAX (DECODE (rn, 1, job))     AS job_1
    ,       MAX (DECODE (rn, 1, max_sal))     AS sal_1
    ,       MAX (DECODE (rn, 2, job))     AS job_2
    ,       MAX (DECODE (rn, 2, max_sal))     AS sal_2
    ,       MAX (DECODE (rn, 3, job))     AS job_3
    ,       MAX (DECODE (rn, 3, max_sal))     AS sal_3
    FROM       (
               SELECT    deptno, dname, loc          -- Changed
               ,          job
               ,          max_sal
               ,          ROW_NUMBER () OVER ( PARTITION BY  deptno      -- , dname, loc     -- Changed
                                              ORDER BY          max_sal      DESC
                                )         AS rn
               FROM     (
                             SELECT    e.deptno, d.dname, d.loc                    -- Changed
                       ,           e.job
                       ,           MAX (e.sal)     AS max_sal
                       FROM      scott.emp        e
                       ,           scott.dept   d
                       WHERE     e.deptno        = d.deptno
                       AND           e.job        IN ('ANALYST', 'CLERK', 'MANAGER')
                       GROUP BY  e.deptno, d.dname, d.loc                    -- Changed
                       ,           e.job
    GROUP BY  deptno, dname, loc                    -- Changed
    ;Actually, you can keep using just deptno in the analytic PARTITION BY clause. It might be a little more efficient to just use deptno, like I did above, but it won't change the results if you use all 3, if there is only 1 danme and 1 loc per deptno.
    By the way, you don't need so many sub-queries. You're using the inner sub-query to compute the MAX, and the outer sub-query to compute rn. Analytic functions are computed after aggregate fucntions, so you can do both in the same sub-query like this:
    SELECT    deptno, dname, loc
    ,       MAX (DECODE (rn, 1, job))     AS job_1
    ,       MAX (DECODE (rn, 1, max_sal))     AS sal_1
    ,       MAX (DECODE (rn, 2, job))     AS job_2
    ,       MAX (DECODE (rn, 2, max_sal))     AS sal_2
    ,       MAX (DECODE (rn, 3, job))     AS job_3
    ,       MAX (DECODE (rn, 3, max_sal))     AS sal_3
    FROM       (
                   SELECT    e.deptno, d.dname, d.loc
              ,       e.job
              ,       MAX (e.sal)     AS max_sal
              ,       ROW_NUMBER () OVER ( PARTITION BY  e.deptno
                                           ORDER BY       MAX (sal)     DESC
                                          )       AS rn
              FROM      scott.emp    e
              ,       scott.dept   d
              WHERE     e.deptno        = d.deptno
              AND       e.job                IN ('ANALYST', 'CLERK', 'MANAGER')
                  GROUP BY  e.deptno, d.dname, d.loc
              ,       e.job
    GROUP BY  deptno, dname, loc
    ;This will work in Oracle 8.1 and up. In Oracle 11, however, it's better to use the SELECT ... PIVOT feature.

  • How can I use lead/lag in this query

    I have written this query which gives me the comparative data based on this week and next week. How can I use Lead/Lag in this query.
       WITH CURRENT_WEEK
              AS (  SELECT   QPAQ.YEAR YEAR,
                             QPAQ.SEASON SEASON,
                             REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+') ACC_SERIES,
                             TO_NUMBER (QPAQ.WEEK) WEEK,
                             MAX (QPAQ.FAILURES) FAILURES
                      FROM   QAR_PLAN_ACC_QTY QPAQ, QAR_PLAN_THRESHOLD_LST QPTL
                     WHERE       QPTL.CATEGORY_ID = 7
                             AND QPAQ.YEAR = QPTL.YEAR
                             AND QPAQ.SEASON = QPTL.SEASON
                             AND QPAQ.SERIES_NAME = QPTL.MODEL_SERIES
                  GROUP BY   QPAQ.YEAR,
                             QPAQ.SEASON,
                             REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+'),
                             TO_NUMBER (QPAQ.WEEK)
                  ORDER BY   REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+')),
           LAST_WEEK
              AS (  SELECT   QPAQ.YEAR YEAR,
                             QPAQ.SEASON SEASON,
                             REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+') ACC_SERIES,
                             TO_NUMBER (QPAQ.WEEK + 1) WEEK,
                             MAX (QPAQ.FAILURES) FAILURES
                      FROM   QAR_PLAN_ACC_QTY QPAQ, QAR_PLAN_THRESHOLD_LST QPTL
                     WHERE       QPTL.CATEGORY_ID = 7
                             AND QPAQ.YEAR = QPTL.YEAR
                             AND QPAQ.SEASON = QPTL.SEASON
                             AND QPAQ.SERIES_NAME = QPTL.MODEL_SERIES
                  GROUP BY   QPAQ.YEAR,
                             QPAQ.SEASON,
                             REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+'),
                             TO_NUMBER (QPAQ.WEEK)
                  ORDER BY   REGEXP_SUBSTR (QPAQ.SERIES_NAME, '[^/]+'))
         SELECT   CURRENT_WEEK.YEAR,
                  CURRENT_WEEK.SEASON,
                  CURRENT_WEEK.ACC_SERIES,
                  CURRENT_WEEK.WEEK,
                  CURRENT_WEEK.FAILURES,
                  (CURRENT_WEEK.FAILURES - LAST_WEEK.FAILURES) FAILURES_COMPARE
           FROM   LAST_WEEK, CURRENT_WEEK
          WHERE   CURRENT_WEEK.WEEK = LAST_WEEK.WEEK(+)
       ORDER BY   CURRENT_WEEK.WEEK;Output is like this.
                    YEAR         SEASON     MODEL                     WEEK        FAILURES    Failures_COMPARE
    1     2011     SUMMER     VGP-BMS15     49     10     
    2     2011     SUMMER     VGP-BMS15     50     28       18
    3     2011     SUMMER     VGP-BMS15     51     30       2
    4     2011     SUMMER     VGP-BMS15     52     40       10Edited by: BluShadow on 06-Jan-2012 13:26
    added {noformat}{noformat} tags. Please read {message:id=9360002} to learn to do this yourself in future.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

    You would jettison the entire LAST_WEEK subquery. Then replace your failure calculation with
        current_week.failure - lag(current_week.failure) over (order by current_week.year, current_week.week) as failures_compareI suppose you might want to think about renaming the sub-query as well ....
    Cheers, APC
    Edited by: APC on Jan 6, 2012 1:41 PM

  • How can i improve this query.

    Hi guys i am beginner , just wanted to know some info , how can i improve this query ..
    select *
    from tableA A, viewB B,
    where A.key = B.key
    and a.criteria1 = '111'
    and a.criteria2 = some_funtion(a.key)
    one more thing should function should be on left side of equal sign.
    will a join make it better or something else is needed more than that .

    952936 wrote:
    Hi guys i am beginner , just wanted to know some info , how can i improve this query ..
    select *
    from tableA A, viewB B,
    where A.key = B.key
    and a.criteria1 = '111'
    and a.criteria2 = some_funtion(a.key)
    one more thing should function should be on left side of equal sign.
    will a join make it better or something else is needed more than that .If you are a beginner try to learn the ANSI Syntax. This will help you a lot to write better queries.
    Your select would look like this in ANSI.
    select *
    from tableA A
    JOIN viewB B ON A.key = B.key
    WHERE a.criteria1 = '111'
    and a.criteria2 = some_function(a.key);The good thing here is that this separates the typical joining part of the select from the typical filter criteria.
    The other syntax very often let you forget one join. Just because there are so many tables and so many filters, that you just don't notice correctly anymore what was join and what not.
    If you notice that the number of column is not what you expect, you can easiely modify the query and compare the results.
    example A
    Remove View B from the query (temporarily comment it out).
    select *
    from tableA A
    --JOIN viewB B ON A.key = B.key
    WHERE a.criteria1 = '111'
    and a.criteria2 = some_funtion(a.key)
    example B
    You notice, that values from A are missing. Maybe because there is no matching key in ViewB? Then change the join to an outer join.
    select *
    from tableA A
    LEFT OUTER JOIN viewB B ON A.key = B.key
    WHERE a.criteria1 = '111'
    and a.criteria2 = some_funtion(a.key)(The outer keyword is optional, left join would be enough).

  • Can I refactor this query to use an index more efficiently?

    I have a members table with fields such as id, last name, first name, address, join date, etc.
    I have a unique index defined on (last_name, join_date, id).
    This query will use the index for a range scan, no sort required since the index will be in order for that range ('Smith'):
    SELECT members.*
            FROM members
            WHERE last_name = 'Smith'
            ORDER BY joindate, idIs there any way I can get something like the following to use the index (with no sort) as well:
    SELECT members.*
            FROM members
            WHERE last_name like 'S%'
            ORDER BY joindate, idI understand the difficulty is probably; even if it does a range scan on every last name 'S%' (assuming it can?), they're not necessarily in order. Case in point:
    Last_Name:  JoinDate:
    Smith          2/5/2010
    Smuckers     1/10/2010An index range scan of 'S%' would return them in the above order, which is not ordered by joindate.
    So is there any way I can refactor this (query or index) such that the index can be range scanned (using LIKE 'x%') and return rows in the correct order without performing a sort? Or is that simply not possible?

    xaeryan wrote:
    I have a members table with fields such as id, last name, first name, address, join date, etc.
    I have a unique index defined on (last_name, join_date, id).
    This query will use the index for a range scan, no sort required since the index will be in order for that range ('Smith'):
    SELECT members.*
    FROM members
    WHERE last_name = 'Smith'
    ORDER BY joindate, idIs there any way I can get something like the following to use the index (with no sort) as well:
    SELECT members.*
    FROM members
    WHERE last_name like 'S%'
    ORDER BY joindate, idI understand the difficulty is probably; even if it does a range scan on every last name 'S%' (assuming it can?), they're not necessarily in order. Case in point:
    Last_Name:  JoinDate:
    Smith          2/5/2010
    Smuckers     1/10/2010An index range scan of 'S%' would return them in the above order, which is not ordered by joindate.
    So is there any way I can refactor this (query or index) such that the index can be range scanned (using LIKE 'x%') and return rows in the correct order without performing a sort? Or is that simply not possible?Come on. Index column order does matter. "LIKE 'x%'" actually is full table scan. The db engine accesses contiguous index entries and then uses the ROWID values in the index to retrieve the table rows.

  • Is there any better way of writing this query??

    I have a query on insert which looks like this,
    INSERT INTO TEMP( I1,I2)
    SELECT TI1 FROM CLIENT1
    WHERE R_CD ='PR' OR 'SR',
    SELECT TI2 FROM CLIENT2
    WHERE R_CD = 'MN' OR 'OP
    There are two tables where the source data is coming from and inserted into TEMP table. I find this query to be inefficient. Anybody who can help me writing a good one?? Thanks.

    <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica">quote:</font><HR>Originally posted by [email protected]:
    I have a query on insert which looks like this,
    INSERT INTO TEMP( I1,I2)
    SELECT TI1 FROM CLIENT1
    WHERE R_CD ='PR' OR 'SR',
    SELECT TI2 FROM CLIENT2
    WHERE R_CD = 'MN' OR 'OP
    There are two tables where the source data is coming from and inserted into TEMP table. I find this query to be inefficient. Anybody who can help me writing a good one?? Thanks.<HR></BLOCKQUOTE>
    A possible solution,
    INSERT INTO TEMP( I1,I2)
    SELECT C1.TI1, C2.TI2
    FROM CLIENT1 C1, CLIENT2 C2
    WHERE (C1.R_CD = 'PR' OR C1.R_CD ='SR') AND
    (C2.R_CD = 'MN' OR C2.R_CD = 'OP')
    null

  • Please can you help me in Tuning this query..?

    Hi ,
    Please can you help me in re-structuring this query? .Details are given below.
    I have 2 tables as shown below and data is like this.
    Position
    COD IND
    AAA N
    BBB N
    CCC N
    DDD Y
    Distance
    orig dest
    AAA BBB
    BBB CCC
    AAA CCC
    I need to create the records like this
    start end
    DDD AAA
    DDD BBB
    DDD CCC
    The query which i am using now for this is
    select p.code AS start,
    P1.CODE AS end
    from position p, position p1
    where
    P.CODE != P1.CODE
    AND (P.ind = 'Y' or P1.IND = 'Y')
    AND not exists
    (select 1
    from distance d
    where (d.orig = p.code or d.dest = p.code)
    and (d.orig = p1.code or d.dest = p1.code))
    table is having above a crore record. so its taking a lot of time.
    Please someone please help in tuning this query?
    Thanks and regards,
    Shabir

    Looks like you want this
    select a.strt, b.ends from
    (select p.code strt from position p where p.ind='Y') a,
    (select p.code ends from position p where p.ind='N') b
    where not exists (select 1 from distance d where d.orig=a.strt or d.dest=a.strt);
    DDD     AAA
    DDD     BBB
    DDD     CCCYour query result is:
    AAA     DDD
    BBB     DDD
    CCC     DDD
    DDD     AAA
    DDD     BBB
    DDD     CCCYou should be more descriptive about what kind of result you want, so that people can get more interested in helping you.

Maybe you are looking for

  • Re: transmission of  schedule lines to vendor

    Dear Experts,                      Schedule lines are generated through MRP, now i need to transmit these schedule lines to my vendor. Pls guide me the steps in doing this. Thanking you, Anil.

  • FSCM via WS-RM (without PI) HTTP message errors

    Hi, ( I'm not sure if this is the correct forum for his question so moderators let me know if not) I am using ECC 6 ehp 5 which enables you to implement FSCM services via WS-RM (Web Service Reliable Messaging) instead of previously having to use PI.

  • Reading files from Java embedding.

    Dear All, My BPEL process has a Java embedding node, and it invokes a Java class, in which an xsl file is being read for transformation. I deploy the xsl files directory together with BPEL package (the jar). In the package, I put the file dir at the

  • Error when reading data from socket

    Hi, I am getting the error 'NiRawReadError: An error occured when reading data from socket.' when using the ABAP API  'mo_core_service->invoke_matching'. And I get this error only when I pass ABAP_TRUE to the paramter 'iv_wait_for_invocation' . Can a

  • Emacs and Xorg

    Hi! I've done a full system upgrade, and xorg and emacs were upgraded to their latest version in the package repository.  When I tried to start emacs afterwards, X crashed.  I've edited my .emacs as the crash was apparently caused by the fact that I