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 PMYour 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 -
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,
NoraTry 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
AdrianUse 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 AMYou 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))
ThanksTry 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,
ShabirLooks 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
-
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