Efficient Query...

Hi ppl if possible please give me a more efficient query which does the same job as follows.....
SELECT order_no order_no,
contract contract,
vendor_no vendor_no
FROM Purchase_Order_Tab p, Purchase_Order_Line_Tab pl
WHERE p.order_no = pl.order_no
AND order_no IN (SELECT DISTINCT(order_no)
FROM (SELECT order_no, line_no, release_no
FROM Purchase_Order_Line_Tab
MINUS
SELECT order_no, line_no, release_no
FROM Purchase_Order_Invoice_Tab))
Thx for ur concern.... :-)

Hi,
Try this:
SELECT order_no order_no,
contract contract,
vendor_no vendor_no
FROM Purchase_Order_Tab p, Purchase_Order_Line_Tab pl
WHERE p.order_no = pl.order_no
AND (pl.order_no, pl.line_no, pl.release_no)
NOT IN (SELECT order_no, line_no, release_no
FROM Purchase_Order_Invoice_Tab)
Note: You can use NOT EXIST also.
** NOT TESTED **
Regards

Similar Messages

  • Suggests for a more efficient query?

    I have a client (customer) that uses a 3rd party software to display graphs of their systems. The clients are constantly asking me (the DBA consultant) to fix the database so it runs faster. I've done as much tuning as I can on the database side. It's now time to address the application issues. The good news is my client is the 4th largest customer of this 3rd party software and the software company has listened and responded in the past to suggestions.
    All of the tables are setup the same with the first column being a DATE datatype and the remaining columns are values for different data points (data_col1, data_col2, etc.). Oh, that first date column is always named "timestamp" in LOWER case so got to use double quotes around that column name all of the time. Each table collects one record per minute per day per year. There are 4 database systems, about 150 tables per system, averaging 20 data columns per table. I did partition each table by month and added a local index on the "timestamp" column. That brought the full table scans down to full partition index scans.
    All of the SELECT queries look like the following with changes in the column name, table name and date ranges. (Yes, we will be addressing the issue of incorporating bind variables for the dates with the software provider.)
    Can anyone suggest a more efficient query? I've been trying some analytic function queries but haven't come up with the correct results yet.
    SELECT "timestamp" AS "timestamp", "DATA_COL1" AS "DATA_COL1"
    FROM "T_TABLE"
    WHERE "timestamp" >=
    (SELECT MIN("tb"."timestamp") AS "timestamp"
    FROM (SELECT MAX("timestamp") AS "timestamp"
    FROM "T_TABLE"
    WHERE "timestamp" <
    TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS')
    UNION
    SELECT MIN("timestamp")
    FROM "T_TABLE"
    WHERE "timestamp" >=
    TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS')) "tb"
    WHERE NOT "timestamp" IS NULL)
    AND "timestamp" <=
    (SELECT MAX("tb"."timestamp") AS "timestamp"
    FROM (SELECT MIN("timestamp") AS "timestamp"
    FROM "T_TABLE"
    WHERE "timestamp" >
    TO_DATE('2006-01-21 12:12:39', 'YYYY-MM-DD HH24:MI:SS')
    UNION
    SELECT MAX("timestamp")
    FROM "T_TABLE"
    WHERE "timestamp" <=
    TO_DATE('2006-01-21 12:12:39', 'YYYY-MM-DD HH24:MI:SS')) "tb"
    WHERE NOT "timestamp" IS NULL)
    ORDER BY "timestamp"
    Here are the queries for a sample table to test with:
    CREATE TABLE T_TABLE
    ( "timestamp" DATE,
    DATA_COL1 NUMBER
    INSERT INTO T_TABLE
    (SELECT TO_DATE('01/20/2006', 'MM/DD/YYYY') + (LEVEL-1) * 1/1440,
    LEVEL * 0.1
    FROM dual CONNECT BY 1=1
    AND LEVEL <= (TO_DATE('01/25/2006','MM/DD/YYYY') - TO_DATE('01/20/2006', 'MM/DD/YYYY'))*1440)
    Thanks.

    No need for analytic functions here (they’ll likely be slower).
    1. No need for UNION ... use UNION ALL.
    2. No need for <quote>WHERE NOT "timestamp" IS NULL</quote> … the MIN and MAX will take care of nulls.
    3. Ask if they really need the data sorted … the s/w with the graphs may do its own sorting
    … in which case take the ORDER BY out too.
    4. Make sure to have indexes on "timestamp".
    What you want to see for those innermost MAX/MIN subqueries are executions like:
    03:19:12 session_148> SELECT MAX(ts) AS ts
    03:19:14   2  FROM "T_TABLE"
    03:19:14   3  WHERE ts < TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS');
    TS
    21-jan-2006 00:12:00
    Execution Plan
       0   SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2.0013301108 Card=1 Bytes=9)
       1    0   SORT (AGGREGATE)
       2    1     FIRST ROW (Cost=2.0013301108 Card=1453 Bytes=13077)
       3    2       INDEX (RANGE SCAN (MIN/MAX))OF 'T_IDX' (INDEX) (Cost=2.0013301108 Card=1453 Bytes=13077)

  • Efficiently Querying Large Table

    I have to query a recordset of 14k records against (join) a very large table: billions of data -even a count of the table does not return any resulty after 15 mins.
    I tried a plsql procedure to store the first recordset in a temp table and then preparing two cursors: one on the temp table and the other on the large table.
    However, the plsql procedure runs for a long time and just gives up with this error:
    SQL> exec match;
    ERROR:
    ORA-01041: internal error. hostdef extension doesn't exist
    BEGIN match; END;
    ERROR at line 1:
    ORA-03113: end-of-file on communication channel
    Is there is way through which I can query more efficiently?
    - Using chucks of records from the large table at a time - how to do that? (rowid)
    - Or just ask the dba to partition the table - but the whole table would still need to be queried.
    The temp table is:
    CREATE TABLE test AS SELECT a.mon_ord_no, a.mo_type_id, a.p2a_pbu_id, a.creation_date,b.status_date_time,
    a.expiry_date, a.current_mo_status_desc_id, a.amount,
    a.purchaser_name, a.recipent_name, a.mo_id_type_id,
    a.mo_redeemed_by_id, a.recipient_type, c.pbu_id, c.txn_seq_no, c.txn_date_time
    FROM mon_order a, mo_status b, host_txn_log c
    where a.mon_ord_no = b.mon_ord_no
    and a.mon_ord_no = c.mon_ord_no
    and b.status_date_time = c.txn_date_time
    and b.status_desc_id = 7
    and a.current_mo_status_desc_id = 7
    and a.amount is not null
    and a.amount > 0
    order by b.status_date_time;
    and the PL/SQL Procedure is:
    CREATE OR REPLACE PROCEDURE MATCH
    IS
    --DECLARE
    deleted INTEGER :=0;
    counter INTEGER :=0;
    CURSOR v_table IS
         SELECT DISTINCT pbu_id, txn_seq_no, create_date
         FROM host_v
         WHERE status = 4;
    v_table_record v_table%ROWTYPE;
    CURSOR temp_table (v_pbu_id NUMBER, v_txn_seq_no NUMBER, v_create_date DATE) IS
         SELECT * FROM test
         WHERE pbu_id = v_pbu_id
         AND txn_seq_no = v_txn_seq_no
         AND creation_date = v_create_date;
    temp_table_record temp_table%ROWTYPE;
    BEGIN
    OPEN v_table;
    LOOP
    FETCH v_table INTO voucher_table_record;
    EXIT WHEN v_table%NOTFOUND;
    OPEN temp_table (v_table_record.pbu_id, v_table_record.txn_seq_no, v_table_record.create_date);
    LOOP
    FETCH temp_table INTO temp_table_record;
    EXIT WHEN temp_table %FOUND;
         DELETE FROM test WHERE pbu_id = v_table_record.pbu_id AND
                   temp_table_record.txn_seq_no = v_table_record.txn_seq_no AND
                   temp_table_record.creation_date = v_table_record.create_date;
    END LOOP;
    CLOSE temp_table;
    END LOOP;
    CLOSE v_table;
    END MATCH;
    /

    Many thanks,
    I can get the explain plan for the SQL statement, but I am not sure how to get it for teh PLSQL. Which section in the PLSQL do I get the explain plan. I am using SQL Navigator.
    I can create the cursor with the join, and if it does not need the delete statement, then there is no need requirement for the procedure itself. Should I just run the query as a SQL statement?
    You have not said what I should do with the rowid?
    Regards

  • 3 Table Joins -- Need a more efficient Query

    I need a 3 table join but need to do it more efficiently than I am currently doing. The query is taking too long to execute (in excess of 20 mins. These are huge tables with 10 mil + records). Here is what the query looks like right now. I need 100 distinct acctnum from the below query with all the conditions as requirements.
    THANKS IN ADVANCE FOR HELP!!!
    SELECT /*+ parallel  */
      FROM (SELECT  /*+ parallel  */  DISTINCT (a.acctnum),
                                  a.acctnum_status,
                                  a.sys_creation_date,
                                  a.sys_update_date,
                                  c.comp_id,
                                  c.comp_lbl_type,
                                  a.account_sub_type
                  FROM   account a
                         LEFT JOIN
                            company c
                         ON a.comp_id = c.comp_id AND c.comp_lbl_type = 'IND',
                         subaccount s
                 WHERE       a.account_type = 'I'
                         AND a.account_status IN ('O', 'S')
                        and s.subaccount_status in ('A','S')
                         AND a.account_sub_type NOT IN ('G', 'V')
                         AND a.SYS_update_DATE <= SYSDATE - 4 / 24)
    where   ROWNUM <= 100 ;

    Hi,
    Whenever you have a question, post CREATE TABLE and INSERT statements for a little sample data, and the results you want from that data.  Explain how you get those results from that data.
    Simplify the problem, if possible.  If you need 100 distinct rows, post a problem where you only need, say, 3 distinct rows.  Just explain that you really need 100, and you'll get a solution that works for either 3 or 100.
    Always say which version of Oracle you're using (e.g. 11.2.0.3.0).
    See the forum FAQ: https://forums.oracle.com/message/9362002
    For tuning problems, also see https://forums.oracle.com/message/9362003
    Are you sure the query you posted is even doing what you want?  You're cross-joining s to the other tables, producing all possible combinations of rows, and then picking 100 of those in no particular order (not even random order).  That's not necessarily wrong, but it certainly is suspicious.
    If you're only interested in 100 rows, there's probably some way to write the query so that it picks 100 rows from the big tables first. 

  • Efficient SQL Query

    Hi,
    I need to write an efficient query because the query involves 4 checks to be performed on rows before returning a single row. Here is a sample query script for creating the table:
    CREATE TABLE "myschema"."Complaint"
         "Compalint_ID" NUMBER(20,0),
         "ReplyTime" NUMBER, -- this would be in minutes
         "CREATION_TIME" TIMESTAMP (6),
    "STATUS" NUMBER,
         "TYPE" NUMBER,
         CONSTRAINT "CH_PKRTBL_Complaint_ID" PRIMARY KEY ("Compalint_ID")
    USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "myspace" ENABLE
    ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "myspace" ;
    CREATE UNIQUE INDEX "myschema"."CH_PKRTBL_Complaint_ID" ON "myschema"."Complaint" ("Compalint_ID")
    PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "myspace" ;
    ALTER TABLE "myschema"."Complaint" ADD CONSTRAINT "CH_PKRTBL_TKTID" PRIMARY KEY ("Compalint_ID")
    USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "myspace" ENABLE;
    I want to write an efficient sql/pl-sql query with least time to return a row based on following four checks/priorities in order spcified below:
    1. Retun any row which has TYPE = 11
    2. If no row found for 1st check then
         calculate a time difference for all rows as: time_difference (CREATION_TIME - ReplyTime)
         and return the row which has largest differene in -ve (that is the row which has expired first)
    3. If now row found for check 2 then
         return row where SATUS = 22
    4. If no row found for check 3 then
         calculate a time difference for all rows as: time_difference (CREATION_TIME - ReplyTime)
         and return the row which has smallest differene in +ve (that is the row which is going to expire next)
    Kindly help me in achieving this task.
    Thanks.

    Just an idea (not sure about the definitions first expired and next to expire )
    select complaint_id,reply_time,creation_time,complaint_status,complaint_type,
      from (select complaint_id,reply_time,creation_time,complaint_status,complaint_type,
                   case complaint_type when 11 then 11 end check1,
                   systimestamp - (creation_time + reply_time / 60/24) check2,
                   case complaint_type when 22 then 22 end check3,
                   systimestamp - (creation_time + reply_time / 60/24) check4,
                   max(case complaint_type when 11 then 11 end) over
                      (order by null rows between unbounded preceding and unbounded following) check1_max,
                   min(case when systimestamp - (creation_time + reply_time / 60/24) < 0
                            then systimestamp - (creation_time + reply_time / 60/24)
                       end
                      ) over
                      (order by null rows between unbounded preceding and unbounded following) check2_max,
                   max(case complaint_type when 22 then 22 end) over
                      (order by null rows between unbounded preceding and unbounded following) check3_max,
                   min(case when systimestamp - (creation_time + reply_time / 60/24) > 0
                            then systimestamp - (creation_time + reply_time / 60/24)
                       end
                      ) over
                      (order by null rows between unbounded preceding and unbounded following) check4_min
              from complaint
    where coalesce(check1,check2,check3,check4) = coalesce(check1_max,check2_max,check3_max,check4_min)Regards
    Etbin

  • Help with query to determine if a record value has changed.

    Our auditors want to know which items had their costs updated in March 2006. I'm querying the cst_standard_cost table to find records that were updated in March. This part seems to be working although it pulls back multiple rows for the same item if more than one update was done in that month. I'm still not sure how I'm going to handle that problem.
    ----cst_standard_costs-----
    alter session set NLS_DATE_FORMAT = 'MM/DD/YYYY';
    drop table suss.cost_update_0306b;
    create table suss.cost_update_0306b
    as
    select csc.inventory_item_id, mtl.segment1||','||mtl.segment2 "item", csc.organization_id,csc.standard_cost,csc.creation_date "creation_date"
    from cst_standard_costs csc, mtl_system_items_b mtl
    where csc.inventory_item_id = mtl.inventory_item_id
    and mtl.organization_id = '82'
    and csc.organization_id not in ('0','81')
    and csc.creation_date like '03/%/2006%'
    order by csc.inventory_item_idHere, I'm trying to find if the update that was done in March actually changed the item's cost. But the sql is not exactly right. The results being returned are any cost update where the item's cost is different than it was in March. I'd like to pull back the item's cost from the most recent cost update previous to the March update and see if it differs from the March cost.
    select csc.inventory_item_id,mtl.segment1||','||mtl.segment2, csc.organization_id,csc.standard_cost, csc.creation_date
    from cst_standard_costs csc, mtl_system_items_b mtl, suss.cost_update_0306b scu
    where csc.inventory_item_id = mtl.inventory_item_id
    and mtl.organization_id = '82'
    and scu.inventory_item_id = csc.inventory_item_id
    and csc.organization_id not in ('0','81')
    and csc.creation_date < scu."creation_date"
    and csc.standard_cost <>scu.standard_cost
    order by csc.inventory_item_id ascHere's a simple example
    item id.....cost.........update_date
    24..........45.00........03/01/2006
    24..........45.00........02/01/2006
    24..........30.00........02/22/2006
    40..........45.00........03/01/2006
    40..........30.00........02/01/2006
    40..........28.00........02/22/2006
    The results of the sql should be to return item id 40 because the costs changed in March but not item id 24 because the costs did not change in March

    Something like this:
    SQL> DESC COSTS;
    Name                                      Null?    Type
    ITEM_ID                                            NUMBER
    COST                                               NUMBER(4,2)
    UPDATE_DATE                                        DATE
    SQL> SELECT * FROM COSTS;
       ITEM_ID       COST UPDATE_DAT
            24         40 03/01/2006
            24         45 02/01/2006
            40         45 03/01/2006
            40         30 02/01/2006
    SQL> SELECT b.item_id, b.cost, b.update_date
      2  FROM costs a, costs b
      3  WHERE a.item_id = b.item_id
      4   AND a.cost <> b.cost
      5   AND a.update_date = ADD_MONTHS(b.update_date, -1)
      6  /
       ITEM_ID       COST UPDATE_DAT
            24         40 03/01/2006
            40         45 03/01/2006It is maybe not efficient query but works :)
    Another solution:
      1  SELECT a.item_id, a.cost, a.update_date
      2  FROM costs a
      3  WHERE a.cost <> (SELECT cost
      4               FROM costs
      5               WHERE a.item_id = item_id
      6                AND ADD_MONTHS(a.update_date, -1) = update_date
      7*            )
    SQL> /
       ITEM_ID       COST UPDATE_DAT
            24         40 03/01/2006
            40         45 03/01/2006Peter D.

  • Delay when querying from CUBE_TABLE object, what is it?

    Hi Guys,
    We are using Oracle OLAP 11.2.0.2.0 with an 11g Cube, 7 Dimensions, Compressed and partitioned by Month.
    We have run into a performance issue when implementing OBIEE.
    The main issue we have is a delay while drilling on a hierarchy. Users have been waiting 7-12 seconds per drill on a hierarchy, and the query is only returning a few cells of data. We have managed to isolate this to slow performing queries on CUBE_TABLE.
    For example, the following query returns one cell of data:
    SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
    FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
    WHERE
    FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
    AND FINSTMNT_VIEW.COMPANY IN ('E01' )
    AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
    AND FINSTMNT_VIEW.PRODUCT IN ('PT' )
    AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
    AND FINSTMNT_VIEW.SITE IN ('C010885' )
    AND FINSTMNT_VIEW.TIME IN ('JUN11' ) ;
    1 Row selected in 4.524 Seconds
    Note: FINSTMNT_VIEW is the automatically generated cube view.
    CREATE OR REPLACE FORCE VIEW "SCHEMA1"."FINSTMNT_VIEW" ("BASE","REPORT_TYPE", "COMPANY", "SCENARIO", "PRODUCT", "ACCOUNT", "SITE", "TIME")
    AS
    SELECT "BASE", "REPORT_TYPE", "COMPANY", "SCENARIO", "PRODUCT", "ACCOUNT", "SITE", "TIME"
    FROM TABLE(CUBE_TABLE('"SCHEMA1"."FINSTMNT"') ) ;
    If we increase the amount of data returned by adding to the query, it only increased the query time by .4 seconds
    SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
    FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
    WHERE
    FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
    AND FINSTMNT_VIEW.COMPANY IN ('E01' )
    AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
    AND FINSTMNT_VIEW.PRODUCT IN ('PT' )
    AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
    AND FINSTMNT_VIEW.SITE IN ('C010885', 'C010886', 'C010891', 'C010892', 'C010887', 'C010888', 'C010897', 'C010893', 'C010890', 'C010894', 'C010896', 'C010899' )
    AND FINSTMNT_VIEW.TIME IN ('JUN11' ) ;
    12 rows selected - In 4.977 Seconds
    If we increase the data returned even more:
    SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
    FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
    WHERE
    FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
    AND FINSTMNT_VIEW.COMPANY IN ('ET', 'E01', 'E02', 'E03', 'E04' )
    AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
    AND FINSTMNT_VIEW.PRODUCT IN ('PT', 'P00' )
    AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
    AND FINSTMNT_VIEW.SITE IN ('C010885', 'C010886', 'C010891', 'C010892', 'C010887', 'C010888', 'C010897', 'C010893', 'C010890', 'C010894', 'C010896', 'C010899' )
    AND FINSTMNT_VIEW.TIME IN ('JUN11', 'JUL11', 'AUG11', 'SEP11', 'OCT11', 'NOV11', 'DEC11', 'JAN12') ;
    118 rows selected - In 14.213 Seconds
    If we take the time for each query and divide by the number of rows, we can see that querying more data results in a much more efficient query:
    Time/Rows returned:
    1 Row - 4.524
    12 Rows - 0.4147
    118 Rows - 0.120449153
    It seems like there is an initial delay of approx 4 seconds when querying the CUBE_TABLE object. Using AWM to query the same data using LIMIT and RPR is almost instantaneous...
    Can anyone explain what this delay is, and if there is any way to optimise the query?
    Could it be the AW getting attached before each query?
    Big thanks to anyone that can help!

    Thanks Nasar,
    I have run a number of queries with logging enabled, the things you mentioned all look good:
    Loop Optimization: GDILoopOpt     COMPLETED
    Selection filter: FILTER_LIMITS_FAST     7
    ROWS_FAILED_FILTER     0
    ROWS_RETURNED     1
    Predicates: 7 pruned out of 7 predicates
    The longest action I have seen in the log is the PAGING operation... but I do not see this on all queries.
    Time Total Time OPERATION
    2.263     27.864          PAGING     DYN_PAGEPOOL     TRACE     GREW     9926KB to 59577KB
    1.825     25.601          PAGING     DYN_PAGEPOOL     TRACE     GREW     8274KB to 49651KB
    1.498     23.776          PAGING     DYN_PAGEPOOL     TRACE     GREW     6895KB to 41377KB
    1.232     22.278          PAGING     DYN_PAGEPOOL     TRACE     GREW     5747KB to 34482KB
    1.17     21.046          PAGING     DYN_PAGEPOOL     TRACE     GREW     4788KB to 28735KB
    1.03     19.876          PAGING     DYN_PAGEPOOL     TRACE     GREW     3990KB to 23947KB
    2.808     18.846          PAGING     DYN_PAGEPOOL     TRACE     GREW     3325KB to 19957KB
    What is strange is that the cube operation log does not account for all of the query time. For example:
    SELECT "BASE_LVL" FROM TABLE(CUBE_TABLE('"EXAMPLE"."FINSTMNT"'))
    WHERE
    "RPT_TYPE" = 'MTD' AND
    "ENTITY" = 'ET' AND
    "SCENARIO" = 'ACTUAL' AND
    "PRODUCT" = 'PT' AND
    "GL_ACCOUNT" = 'APBIT' AND
    "CENTRE" = 'TOTAL' AND
    "TIME" = 'YR09';
    This query returns in 6.006 seconds using SQL Developer, if I then take the CUBE_OPERATION_LOG for this query and subtract the start time from the end time, I only get 1.67 seconds. This leaves 4.3 seconds unaccounted for... This is the same with the my other queries, see actual time and logged time below:
    Query     Actual     Logged      Variance
    S3     6.006     1.67     4.336
    L1     18.128     13.776     4.352
    S1     4.461     0.203     4.258
    L2     4.696     0.39     4.306
    S2     5.882     1.575     4.307
    Any ideas on what this could be or how I can capture this 4.3 second overhead?
    Your help has been greatly appreciated.

  • How to measure the performance of sql query?

    Hi Experts,
    How to measure the performance, efficiency and cpu cost of a sql query?
    What are all the measures available for an sql query?
    How to identify i am writing optimal query?
    I am using Oracle 9i...
    It ll be useful for me to write efficient query....
    Thanks & Regards

    psram wrote:
    Hi Experts,
    How to measure the performance, efficiency and cpu cost of a sql query?
    What are all the measures available for an sql query?
    How to identify i am writing optimal query?
    I am using Oracle 9i... You might want to start with a feature of SQL*Plus: The AUTOTRACE (TRACEONLY) option which executes your statement, fetches all records (if there is something to fetch) and shows you some basic statistics information, which include the number of logical I/Os performed, number of sorts etc.
    This gives you an indication of the effectiveness of your statement, so that can check how many logical I/Os (and physical reads) had to be performed.
    Note however that there are more things to consider, as you've already mentioned: The CPU bit is not included in these statistics, and the work performed by SQL workareas (e.g. by hash joins) is also credited only very limited (number of sorts), but e.g. it doesn't cover any writes to temporary segments due to sort or hash operations spilling to disk etc.
    You can use the following approach to get a deeper understanding of the operations performed by each row source:
    alter session set statistics_level=all;
    alter session set timed_statistics = true;
    select /* findme */ ... <your query here>
    SELECT
             SUBSTR(LPAD(' ',DEPTH - 1)||OPERATION||' '||OBJECT_NAME,1,40) OPERATION,
             OBJECT_NAME,
             CARDINALITY,
             LAST_OUTPUT_ROWS,
             LAST_CR_BUFFER_GETS,
             LAST_DISK_READS,
             LAST_DISK_WRITES,
    FROM     V$SQL_PLAN_STATISTICS_ALL P,
             (SELECT *
              FROM   (SELECT   *
                      FROM     V$SQL
                      WHERE    SQL_TEXT LIKE '%findme%'
                               AND SQL_TEXT NOT LIKE '%V$SQL%'
                               AND PARSING_USER_ID = SYS_CONTEXT('USERENV','CURRENT_USERID')
                      ORDER BY LAST_LOAD_TIME DESC)
              WHERE  ROWNUM < 2) S
    WHERE    S.HASH_VALUE = P.HASH_VALUE
             AND S.CHILD_NUMBER = P.CHILD_NUMBER
    ORDER BY ID
    /Check the V$SQL_PLAN_STATISTICS_ALL view for more statistics available. In 10g there is a convenient function DBMS_XPLAN.DISPLAY_CURSOR which can show this information with a single call, but in 9i you need to do it yourself.
    Note that "statistics_level=all" adds a significant overhead to the processing, so use with care and only when required:
    http://jonathanlewis.wordpress.com/2007/11/25/gather_plan_statistics/
    http://jonathanlewis.wordpress.com/2007/04/26/heisenberg/
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Tricky SQL query... how to get all data in a single query?

    create table employee_definition (def_id number, def_name varchar(50));
    insert into employee_definition values (100, 'EMAIL');
    insert into employee_definition values (200, 'MOBILE_PHONE');
    insert into employee_definition values (300, 'HOME_PHONE');
    SQL> select * from employee_definition;
        DEF_ID DEF_NAME
           100 EMAIL
           200 MOBILE_PHONE
           300 HOME_PHONE
    create table employee_data (def_id number, def_value varchar(20), emp_id number);
    insert into employee_data values (100, '[email protected]', 123);
    insert into employee_data values (200, '01232222', 123);
    insert into employee_data values (300, '5555', 123);
    insert into employee_data values (100, '[email protected]', 666);
    insert into employee_data values (200, '888', 666);
    insert into employee_data values (300, '999', 666);
    insert into employee_data values (300, '444', 777);
    SQL> select * from employee_data;
        DEF_ID DEF_VALUE                EMP_ID
           100 [email protected]              123
           200 01232222                    123
           300 5555                        123
           100 [email protected]              666
           200 888                         666
           300 999                         666
           300 999                         777
    7 rows selected.I'm supposed to create a SQL that will return me the email, mobile_phone, and home_phone for a set of employees. The result will be something like this:
    EMPLOYEE ID | HOME_PHONE | MOBILE_PHONE | EMAIL
    123         |  5555  |    01232222      | [email protected]
    666         |  999  |    888      | [email protected]
    777         |  444  |    null     | nullThe thing I'm finding difficulty here is that the same column is used to store different values, based on the value in employee_definition table (something like a key/value pair). If I do:
    SQL> select emp_id, def_value as email from employee_data, employee_definition
      2  where employee_data.def_id = employee_definition.def_id
      3  and employee_definition.def_name = 'EMAIL';
        EMP_ID EMAIL
           123 [email protected]
           666 [email protected]'s partially ok.. I'm just getting the definition for 'EMAIL'. But how can I get all the values in a single query, knowing that the column stores different values based on def_name?

    Oh no, not again.
    Entity attribute models always seem like a great idea to people who have been in the profession for five minutes and lack any kind of fundamental knowledge.
    It staggers me that someone with 2,345 posts still believes "you need a 'detail table' for [storing multiple telephone numbers]"
    "A person can have multiple telephone numbers" is not an excuse to build a tired person_attribute table. Niether is the bizarre proposal by someone with over 4k posts who should know better in an earlier post that EAV models are necessary to support temporal fidelity.
    Taken to it's logical conclusion, EAV modelling leads to just two application tables. THINGS and THING_ATTRIBUTES. And when you consider that a THING_ATTRIBUTE is also a THING, why not roll those two tables up into one also? Hmmm, what does THINGS and THING_ATTRIBUTES look like? I know, TABLES and COLUMNS. Who would've guessed? SQL already provides the completely flexible extensible attribute model the advocates of EAV proscribe. But it also has data types, physical data independence, constraints and an efficient query language which EAV does not.
    EAV modelling errodes the semantics of the attributes which are bundled into the "attribute" table.
    There is no point in storing 12 different phone numbers with implied functional dependency to unconstrained and often repeating notional attributes like "MOBILE", "LANDLINE", "WORK", err, "WORK2", err, "MOBILE2", err, ... when this phone type attribute has no semantic value. When you want to call someone, you invariably want to retrive the prefered_phone_number which may depend on a time of day, or a call context.
    These things need to be modelled properly (i.e normalised to BCNF) within the context of the database.

  • A more efficient way to assure that a string value contains only numbers?

    Hi ,
    I'm using Oracle 9.2.0.6.
    I was curious to know if there was any way I could write a more efficient query to determine if a string value contains only numbers.
    Here's my current query. This SQL is from a sub query in a Join clause.
    select distinct cta.CUSTOMER_TRX_ID, to_number(cta.SALES_ORDER) SALES_ORDER
                from ra_customer_trx_lines_all cta
                where length(cta.SALES_ORDER) = 6
                and cta.SALES_ORDER is not null
                and substr(cta.SALES_ORDER,1,1) in('1','2','3','4','5','6','7','8','9','0')
                and substr(cta.SALES_ORDER,2,1) in('1','2','3','4','5','6','7','8','9','0')
                and substr(cta.SALES_ORDER,3,1) in('1','2','3','4','5','6','7','8','9','0')
                and substr(cta.SALES_ORDER,4,1) in('1','2','3','4','5','6','7','8','9','0')
                and substr(cta.SALES_ORDER,5,1) in('1','2','3','4','5','6','7','8','9','0')
                and substr(cta.SALES_ORDER,6,1) in('1','2','3','4','5','6','7','8','9','0')This is a string where I'm finding A-Z-a-z characters and '/' and '-' characters in all 6 positions, plus there are values that are longer than 6 characters. That's what the length(cta.SALES_ORDER) = 6 is for. Also, of course. some cells are NULL.
    So the question is, is there a more efficient way to screen out only the values in this field that are 6 character numbers or is what I have the best I can do?
    Thanks,

    I appreciate all of your very helpfull workarounds. The cost is a little better in all cases than my original where clause.
    To address the discussion that's popped up about design from this question, I can say a few things that should clear , at least, my situation up.
    First of all this custom quoting , purchase order , and sales order entry system WAS written by a bunch a of 'bad' coders who didn't document their work and then left. We don't even have an ER diagram
    The whole project that I'm only a small part of is literally trying to put Humpty Dumpty together again and then move it from a bad custom solution into Oracle Applications.
    We're rebuilding, documenting, and doing ETL. This is one of your prototypical projects from hell.
    It's a huge database project so we're taking small bites as a time. Hopefully, somewhere right before Armageddon hits, this thing will be complete.
    But until then,..., well,..., you know the drill.
    Thanks Again.

  • Partition Table Query taking Too Much Time

    I have created partition table and Created local partition index on a column whose datatype is DATE.
    Now when I Query table and use index column in the where clause It is scaning all the table (Full scan) . The quey is :
    Select * From mytable
    where to_char(transaction_date, 'DD-MON-YY') = '01-Aug-07';
    I have to use to_char function not to_date due to Front end application problem.

    Before we go too far with this, if you manually query with TO_DATE on the variable instead of TO_CHAR on the column, does the query actually use the index?
    The TO_CHAR on the column will definitely stop Oracle from using any index on the column. If the query will use the index if you TO_DATE the variable, as I see it, you have three options. First, fix the application problem that won't let you use TO_DATE from the application. Second, change the application to call a function returning a ref cursor, get the date string as a parameter to the function, and do the TO_DATE in the function.
    Third, you could consider creating a function-based index on TO_CHAR(transaction_date, 'dd-Mon-yy'). This would be the least desirable option, particularly if you would also be selecting records based on a range of transaction_dates, since it loses a lot of information that the optimizer could use in devising an efficient query plan. It could also change your results for a range scan.
    John

  • How to Efficiently Sample a Fixed Number of Rows

    Good afternoon. I need to select a specific number of random rows from a table, and while I believe my logic is right it's taking too long, 30 minutes for a routine data size. Hopefully someone here can show me a more efficient query. I've seen the SAMPLE function, but it just randomly selects rows on a one-by-one basis, without a guaranteed total count.
    This is the idea:
    INSERT INTO Tmp_Table (Value, Sequence) SELECT Value FROM Perm_Table, DBMS_RANDOM.VALUE;
    SELECT Value FROM Tmp_Table WHERE ROWNUM <= 1234 ORDER BY Sequence;I'd need to put the ORDER BY in a subselect for ROWNUM to work correctly, but anyway that's just an illustration. My actual need is a little more complicated. I have many sets of data; each set has many rows; and for each set I need to return a specific (different) number of rows. Perhaps project A has three rows in this table, and I want to keep two of them; project B has two rows, and I want to keep one of them. So I need to identify, for each row, whether it's valid for that project. This is what my data looks like:
    Project Person  Sequence Position Keeper
    A       Bill    1234     1        Yes
    A       Fred    5678     3        No
    A       George  1927     2        Yes
    B       April   5784     2        No
    B       Janice  2691     1        YesI populate Sequence with random values, then calculate the position of each person within their project, and finally discard people who's Position is greater than Max_Targets for the Project. Fred and April have the highest random numbers, so they're cut. It's not the case that I'm just trimming one person from each project; the actual percentage kept will range from zero to 100.
    Populating the list with random values is not time-consuming, but calculating Position is. This is my code:
    UPDATE Tmp_Targets T1
    SET Position =
      SELECT
       COUNT(*)
      FROM
       Perm_Targets PT1
       INNER JOIN Perm_Targets PT2 ON PT1.Project = PT2.Project
       INNER JOIN Tmp_Targets T2 ON PT2.Target = T2.Target
      WHERE
           T1.Target = PT1.Target
       AND T2.Sequence <= T1.Sequence
      );The Target fields are PKs, and the Project and Sequence fields are indexed. Is there a better way to approach this? I could write a cursor that pulls out project codes and performs the above operations for each project in turn; that would be logically simpler and possibly faster. Has anyone here addressed a similar problem before? I'd appreciate any ideas.
    This is on 9.2, in case it matters. Thank you,
    Jonathan

    You've not given any indication of how max targets for a given project is determined, so for my example I'm using the ceiling of 1/2 of the number of records in each project which gives the same number of yes and no responses per project as you had:
    with dta as (
      select 'A' project, 'Bill' person from dual union all
      select 'A', 'Fred' from dual union all
      select 'A', 'George' from dual union all
      select 'B', 'April' from dual union all
      select 'B', 'Janice' from dual
    ), t1 as (
      select project
           , person
           , row_number() over (partition by project order by dbms_random.value) ord
           , count(*) over (partition by project) cnt
           , rownum rn
        from dta
    select project
         , person
         , ord
         , cnt
         , case when ord <= ceil(cnt/2) then 'Yes' else 'No' end keep
      from t1
      order by rn
    PROJECT PERSON ORD                    CNT                    KEEP
    A       Bill   2                      3                      Yes 
    A       Fred   3                      3                      No  
    A       George 1                      3                      Yes 
    B       April  1                      2                      Yes 
    B       Janice 2                      2                      No  
    5 rows selectedIn this example I use an analytic function to assign a random ordering for each record within a project in the middle query, in the final output query I am determining the yes no status based on the order within a project and the count of records in the project. If you had a table of projects indicating the thresh hold you could join to that and use the thresh hold in place of the ceil(cnt/2) portion of my inequality in the case statement.

  • Query on column with comma separated values

    I have a proposed table with unnormalized data like the following:
    ID COLA COLB REFLIST
    21 xxx  zzz  24,25,78,412
    22 xxx  xxx  21
    24 yyy  xxx  912,22
    25 zzz  fff  433,555,22
    .. ...  ...  ...There are 200 million rows. There is maximum of about 10 IDs in the REFLIST, though typically two or three. How could I efficiently query this data on the REFLIST column? e.g. something like:
    SELECT id FROM mytable WHERE :myval in reflistLogically there is a many to many relationship between rows in this table. The REFLIST column contains pointers to ID values elsewhere in the table. The data could be normalized so that the relationship keys are in a separate table (in fact this is the current solution that we want to change).
    ID  REF
    21  24
    21  25
    21  78
    21  412
    22  21
    24  912
    ... ...The comma separated list seems instinctively like a bad idea, however there are various reasons for proposing it. The main reason is because the source for this data has it structured like the REFLIST example. It is an OLTP-like system rather than a data warehouse. The source code (and edit performance) would benefit greatly from not having to maintain the relationship table as the data changes.
    Going back to querying the REFLIST column, the problem seems to be building an approriate index for the data. The ideas proposed so far are:
    <li>Make a materialized view that presents the relationships as normalized (e.g. as in the example with ID, REF columns above), then index the plain column - the various methods of writing the view SQL have been widely posted.
    <li>Use a Oracle Text Index (not something I have ever had call to use before).
    Any other ideas? Its Oracle 10.2, though 11g could be possible.
    Thanks
    Jim

    Something like this ?
    This is test demo on my 11.2.0.1 Windows XP
    SQL> create table test (id number,reflist varchar2(30));
    Table created.
    SQL> insert into test values (21,'24,25,78,412');
    1 row created.
    SQL> insert into test values (22,'21');
    1 row created.
    SQL> insert into test values (24,'912,22');
    1 row created.
    SQL> insert into test values (25,'433,555,22');
    1 row created.
    SQL> select * from test
      2  where
      3  ',' || reflist || ',' like '%,22,%';
            ID REFLIST
            24 912,22
            25 433,555,22
    SQL>Source:http://stackoverflow.com/questions/7212282/is-it-possible-to-query-a-comma-separated-column-for-a-specific-value
    Regards
    Girish Sharma
    Edited by: Girish Sharma on Jul 12, 2012 2:31 PM

  • Tuning Oracle query

    Hi,
    when I run this query:
    SELECT a.*, d.C1
      FROM t1 a, t2 b, t3 c, t4 d
    WHERE C2 IS NOT NULL
       AND C1 > '0005'
       AND a.C3 = b.C4
       AND NOT EXISTS (
              SELECT *
                FROM t5
               WHERE C5 = C2
                 AND C6 = DECODE (b.C7,'AB', 0,
                                  'BC', '555',
                                  a.C3
       AND a.C2 = c.C5
       AND a.C8 = d.C8;It is taking lot of time (more 1 hour), I need some suggestions how to tune it.
    I have noticed that If I remove the "NOT EXISTS" clause the query becomes very fast.
    I'd like to know How Can I write more efficient query, and speed up existing code.
    Thanks in advance!

    Below ddl and explan plan of the query:
       CREATE TABLE t4
      ID_C            NUMBER                      NOT NULL,
      C1         VARCHAR2(14 BYTE)
    | Id  | Operation                    | Name              | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT             |                   |   103K|    12M|       |   451K  (1)| 01:30:17 |
    |*  1 |  FILTER                      |                   |       |       |       |            |          |
    |*  2 |   HASH JOIN                  |                   |   103K|    12M|       | 57064   (1)| 00:11:25 |
    |   3 |    TABLE ACCESS FULL         | t2                |    66 |   528 |       |     3   (0)| 00:00:01 |
    |   4 |    NESTED LOOPS              |                   |   103K|    11M|       | 57059   (1)| 00:11:25 |
    |*  5 |     HASH JOIN                |                   |   106K|    11M|  3440K| 57051   (1)| 00:11:25 |
    |*  6 |      TABLE ACCESS FULL       | t4                |   106K|  2188K|       |  2012   (2)| 00:00:25 |
    |*  7 |      TABLE ACCESS FULL       | t1                |  6343K|   568M|       | 22970   (2)| 00:04:36 |
    |*  8 |     INDEX UNIQUE SCAN        | SYS_C0020000      |     1 |     6 |       |     1   (0)| 00:00:01 |
    |*  9 |   TABLE ACCESS BY INDEX ROWID| t5                |     1 |     9 |       |     4   (0)| 00:00:01 |
    |* 10 |    INDEX RANGE SCAN          | IDX_C             |     1 |       |       |     2   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------------------------

  • Tune the query with join and not exists

    This is on 10g R2.
    I have a query similar to :
    Select A.*, C.*
    From A inner join B on A.id = B.id
    Left join C on A.kid = C.kid
    Where not exists
    (select * from D where A.fid = D.fid and A.stat = 2);
    I want avoiding to use the NOT EXISTS in the last part of the query
    I tried the autotrace explain of above and compared with others format and found no better execution plan than that. The explain plan indicated that there were long "table access full" operation on B, due to its little huge records, and a long operation of the "NESTED LOOPS OUTER". I had tried to replace the NOT EXISTS part with another LEFT JOIN in the FROM, but it went worse. So Anyone can suggest a better way? or it is the most efficient query I can get?

    Here is the tkprof output
    from baandb.ttfacr200201 a
       inner join baandb.ttfgld106201 c on (a.t$ttyp = c.t$otyp and a.t$ninv = c.t$odoc) and c.t$leac like :"SYS_B_0"
       left join baandb.ttfgld910201 d on c.t$dim2 = d.t$dimx and d.t$dtyp = :"SYS_B_1"
       where not exists
        (select * from baandb.tcisli205201 b
         where a.t$ttyp = b.t$ityp and a.t$ninv = b.t$idoc)
         and (a.t$trec = :"SYS_B_2" or a.t$trec = :"SYS_B_3" and t$tdoc = :"SYS_B_4")
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.01       0.01          0          0          0           0
    Fetch        5      1.06      52.11      29925      45943          0          54
    total        7      1.07      52.12      29925      45943          0          54
    Misses in library cache during parse: 1
    Misses in library cache during execute: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 31
    Rows     Row Source Operation
         54  HASH JOIN RIGHT ANTI (cr=45943 pr=29925 pw=0 time=2317005 us)
       9957   INDEX FAST FULL SCAN TCISLI205201$IDX1 (cr=39 pr=0 pw=0 time=54 us)(object id 16639)
      10067   NESTED LOOPS OUTER (cr=45904 pr=29925 pw=0 time=68531937 us)
      10067    HASH JOIN  (cr=35837 pr=29925 pw=0 time=68471521 us)
      10420     TABLE ACCESS FULL TTFACR200201 (cr=2424 pr=0 pw=0 time=20894 us)
      33156     TABLE ACCESS FULL TTFGLD106201 (cr=33413 pr=29925 pw=0 time=117767552 us)
         51    INDEX UNIQUE SCAN TTFGLD910201$IDX1 (cr=10067 pr=0 pw=0 time=53177 us)(object id 20402)
    OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        2      0.00       0.00          0          0          0           0
    Execute      3      0.02       0.02          0          0          0           0
    Fetch        6      1.06      52.11      29925      45943          0          55
    total       11      1.08      52.14      29925      45943          0          55

Maybe you are looking for