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
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 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 -
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. -
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 can i make the optimiser to skip this full table scan ??
Hi,
I am trying to tune the below query, I have checked up all the possibilities to skip the full table scan on vhd_calldesh_archive, But am unable to find the predicate in the where clause, which is letting the optimiser to choose the full table scan on vhd_calldesk_archive table, which is very large one. how can i make the optimiser to skip this full table scan.
Please check the below sql script and explain plan ,
SELECT a.call_id, a.entry_date,
NVL (INITCAP (b.full_name), caller_name) AS caller_name,
c.description AS org_desc, a.env_id, i.env_desc, a.appl_id,
d.appl_desc, a.module_id, e.module_desc, a.call_type_id,
f.call_type_desc, a.priority, a.upduserid,
INITCAP (g.full_name) AS lastupdated_username, a.call_desc, h.mode_desc,
a.received_time,a.assignment_team, a.status,
ROUND (lcc.pkg_com.fn_datediff ('MI',
a.entry_date,
a.status_date
) AS elapsed_time,
ROUND (lcc.pkg_com.fn_datediff ('MI',
a.entry_date,
a.status_date
) AS resolved_min,
CASE
WHEN a.orgid in (1,100,200) THEN a.orgid
ELSE j.regionorgid
END AS region
,(SELECT coalesce(MAX(upddate),a.upddate) FROM lcc.vhd_callstatus stat WHERE stat.call_id = a.call_id
) as stat_upddate
,(SELECT team_desc from lcc.vhd_teams t where t.team_id = a.assignment_team) as team_desc
,a.eta_date
,coalesce(a.caller_contact, b.telephone) AS caller_contact
,coalesce(a.caller_email, b.email) as email
,a.affected_users
,a.outage_time
,a.QA_DONE
,a.LAST_ACTION_TEAM
,a.LAST_ACTION_USER
,INITCAP (k.full_name) AS last_action_username
,a.last_action_date
,l.team_desc as last_action_teamdesc
,a.refid
,INITCAP (lu.full_name) AS logged_name
,a.pmreview
,a.status as main_status
FROM lcc.vhd_calldesk_archive a
LEFT OUTER JOIN lcc.lcc_userinfo_details b ON b.user_name = a.caller_id
INNER JOIN lcc.com_organization c ON c.code = a.orgid
INNER JOIN lcc.vhd_applications d ON d.appl_id = a.appl_id
INNER JOIN lcc.vhd_modules e ON e.appl_id = a.appl_id AND e.module_id = a.module_id
INNER JOIN lcc.vhd_calltypes f ON f.call_type_id = a.call_type_id
INNER JOIN lcc.com_rptorganization j ON j.orgid = a.orgid AND j.tree = 'HLPDK'
LEFT OUTER JOIN lcc.lcc_userinfo_details g ON g.user_name = a.upduserid
LEFT OUTER JOIN lcc.vhd_callmode h ON h.mode_id = a.mode_id
LEFT OUTER JOIN lcc.vhd_environment i ON i.appl_id = a.appl_id AND i.env_id = a.env_id
LEFT OUTER JOIN lcc.lcc_userinfo_details k ON k.user_name = a.last_action_user
LEFT OUTER JOIN lcc.vhd_teams l ON l.team_id = a.last_action_user
LEFT OUTER JOIN (select CALL_ID,upduserid FROM lcc.VHD_CALLDESK_HISTORY P where upddate
in ( select min(upddate) from lcc.VHD_CALLDESK_HISTORY Q WHERE Q.CALL_ID = P.CALL_ID
group by call_id)) ku
ON ku.call_id = a.call_id
LEFT OUTER JOIN lcc.lcc_userinfo_details lu ON NVL(ku.upduserid,A.upduserid) = lu.user_name;
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 2104 | 3667K| 37696 |
| 1 | UNION-ALL | | | | |
| 2 | NESTED LOOPS OUTER | | 2103 | 3665K| 37683 |
| 3 | VIEW | | 2103 | 3616K| 35580 |
| 4 | NESTED LOOPS OUTER | | 2103 | 823K| 35580 |
| 5 | NESTED LOOPS OUTER | | 2103 | 774K| 33477 |
| 6 | NESTED LOOPS OUTER | | 2103 | 685K| 31374 |
| 7 | NESTED LOOPS | | 2103 | 636K| 29271 |
| 8 | NESTED LOOPS | | 2103 | 603K| 27168 |
| 9 | NESTED LOOPS OUTER | | 2103 | 558K| 25065 |
| 10 | NESTED LOOPS OUTER | | 2103 | 515K| 22962 |
| 11 | NESTED LOOPS | | 2103 | 472K| 20859 |
| 12 | NESTED LOOPS | | 2103 | 429K| 18756 |
| 13 | NESTED LOOPS OUTER | | 4826 | 890K| 13930 |
| 14 | NESTED LOOPS OUTER | | 4826 | 848K| 9104 |
| 15 | NESTED LOOPS | | 4826 | 754K| 4278 |
|* 16 | TABLE ACCESS FULL | COM_RPTORGANIZATION | 75 | 1050 | 3 |
| 17 | TABLE ACCESS BY INDEX ROWID | VHD_CALLDESK | 64 | 9344 | 57 |
|* 18 | INDEX RANGE SCAN | VHD_CALLDSK_ORGID | 2476 | | 7 |
| 19 | VIEW PUSHED PREDICATE | | 1 | 20 | 1 |
|* 20 | FILTER | | | | |
| 21 | TABLE ACCESS BY INDEX ROWID | VHD_CALLDESK_HISTORY | 1 | 20 | 2 |
|* 22 | INDEX RANGE SCAN | VHD_CALLDSK_HIST_CALLID_IDX | 1 | | 1 |
|* 23 | FILTER | | | | |
| 24 | SORT GROUP BY NOSORT | | 1 | 12 | 2 |
| 25 | TABLE ACCESS BY INDEX ROWID | VHD_CALLDESK_HISTORY | 1 | 12 | 2 |
|* 26 | INDEX RANGE SCAN | VHD_CALLDSK_HIST_CALLID_IDX | 1 | | 1 |
| 27 | TABLE ACCESS BY INDEX ROWID | VHD_CALLMODE | 1 | 9 | 1 |
|* 28 | INDEX UNIQUE SCAN | VHD_CALLMOD_MODID_PK | 1 | | |
| 29 | TABLE ACCESS BY INDEX ROWID | VHD_APPLICATIONS | 1 | 20 | 1 |
|* 30 | INDEX UNIQUE SCAN | VHD_APPL_APPLID_PK | 1 | | |
| 31 | TABLE ACCESS BY INDEX ROWID | VHD_CALLTYPES | 1 | 21 | 1 |
|* 32 | INDEX UNIQUE SCAN | VHD_CALLTYP_ID_PK | 1 | | |
| 33 | TABLE ACCESS BY INDEX ROWID | VHD_TEAMS | 1 | 21 | 1 |
|* 34 | INDEX UNIQUE SCAN | VHD_TEAMID_PK | 1 | | |
| 35 | TABLE ACCESS BY INDEX ROWID | VHD_ENVIRONMENT | 1 | 21 | 1 |
|* 36 | INDEX UNIQUE SCAN | VHD_ENV_APLENVID_PK | 1 | | |
| 37 | TABLE ACCESS BY INDEX ROWID | VHD_MODULES | 1 | 22 | 1 |
|* 38 | INDEX UNIQUE SCAN | VHD_MOD_APLMOD_ID_PK | 1 | | |
| 39 | TABLE ACCESS BY INDEX ROWID | COM_ORGANIZATION | 1 | 16 | 1 |
|* 40 | INDEX UNIQUE SCAN | COM_ORG_PK | 1 | | |
| 41 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 |
|* 42 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 43 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 43 |
|* 44 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 45 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 | 1
|* 46 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 47 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 | 1
|* 48 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 49 | NESTED LOOPS OUTER | | 1 | 1785 | 13 |
| 50 | VIEW | | 1 | 1761 | 12 |
| 51 | NESTED LOOPS OUTER | | 1 | 1656 | 12 |
| 52 | NESTED LOOPS OUTER | | 1 | 1632 | 11 |
| 53 | NESTED LOOPS OUTER | | 1 | 1608 | 10 |
| 54 | NESTED LOOPS | | 1 | 1565 | 9 |
| 55 | NESTED LOOPS | | 1 | 1549 | 9 |
| 56 | NESTED LOOPS | | 1 | 1535 | 9 |
| 57 | NESTED LOOPS OUTER | | 1 | 1513 | 8 |
| 58 | NESTED LOOPS OUTER | | 1 | 1492 | 7 |
| 59 | NESTED LOOPS | | 1 | 1471 | 6 |
| 60 | NESTED LOOPS | | 1 | 1450 | 5 |
| 61 | NESTED LOOPS OUTER | | 1 | 1430 | 4 |
| 62 | NESTED LOOPS OUTER | | 1 | 1421 | 3 |
| 63 | TABLE ACCESS FULL | VHD_CALLDESK_ARCHIVE | 1 | 1401 | 2 |
| 64 | VIEW PUSHED PREDICATE | | 1 | 20 | 1 |
|* 65 | FILTER | | | | |
| 66 | TABLE ACCESS BY INDEX ROWID | VHD_CALLDESK_HISTORY | 1 | 20 | 2 |
|* 67 | INDEX RANGE SCAN | VHD_CALLDSK_HIST_CALLID_IDX | 1 | | 1 |
|* 68 | FILTER | | | | |
| 69 | SORT GROUP BY NOSORT | | 1 | 12 | 2 |
| 70 | TABLE ACCESS BY INDEX ROWID| VHD_CALLDESK_HISTORY | 1 | 12 | 2 |
|* 71 | INDEX RANGE SCAN | VHD_CALLDSK_HIST_CALLID_IDX | 1 | | 1 |
| 72 | TABLE ACCESS BY INDEX ROWID | VHD_CALLMODE | 1 | 9 | 1 |
|* 73 | INDEX UNIQUE SCAN | VHD_CALLMOD_MODID_PK | 1 | | |
| 74 | TABLE ACCESS BY INDEX ROWID | VHD_APPLICATIONS | 1 | 20 | 1 |
|* 75 | INDEX UNIQUE SCAN | VHD_APPL_APPLID_PK | 1 | | |
| 76 | TABLE ACCESS BY INDEX ROWID | VHD_CALLTYPES | 1 | 21 | 1 |
|* 77 | INDEX UNIQUE SCAN | VHD_CALLTYP_ID_PK | 1 | | |
| 78 | TABLE ACCESS BY INDEX ROWID | VHD_TEAMS | 1 | 21 | 1 |
|* 79 | INDEX UNIQUE SCAN | VHD_TEAMID_PK | 1 | | |
| 80 | TABLE ACCESS BY INDEX ROWID | VHD_ENVIRONMENT | 1 | 21 | 1 |
|* 81 | INDEX UNIQUE SCAN | VHD_ENV_APLENVID_PK | 1 | | |
| 82 | TABLE ACCESS BY INDEX ROWID | VHD_MODULES | 1 | 22 | 1 |
|* 83 | INDEX UNIQUE SCAN | VHD_MOD_APLMOD_ID_PK | 1 | | |
| 84 | TABLE ACCESS BY INDEX ROWID | COM_RPTORGANIZATION | 1 | 14 | |
|* 85 | INDEX UNIQUE SCAN | COM_RPTORG_PK | 1 | | |
| 86 | TABLE ACCESS BY INDEX ROWID | COM_ORGANIZATION | 1 | 16 | |
|* 87 | INDEX UNIQUE SCAN | COM_ORG_PK | 1 | | |
| 88 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 43 |
|* 89 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 90 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 |
|* 91 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 92 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 | 1
|* 93 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
| 94 | TABLE ACCESS BY INDEX ROWID | LCC_USERINFO_DETAILS | 1 | 24 | 1
|* 95 | INDEX UNIQUE SCAN | LCCUSERINFOIND | 1 | | |
Predicate Information (identified by operation id):
16 - filter("J"."TREE"='HLPDK')
18 - access("J"."ORGID"="A"."ORGID")
20 - filter( EXISTS (SELECT /*+ */ 0 FROM "LCC"."VHD_CALLDESK_HISTORY" "Q" WHERE "Q"."CALL_ID"=:B1
"Q"."CALL_ID" HAVING MIN("Q"."UPDDATE")=:B2))
22 - access("SYS_ALIAS_2"."CALL_ID"="A"."CALL_ID")
23 - filter(MIN("Q"."UPDDATE")=:B1)
26 - access("Q"."CALL_ID"=:B1)
28 - access("H"."MODE_ID"(+)="A"."MODE_ID")
30 - access("D"."APPL_ID"="A"."APPL_ID")
32 - access("F"."CALL_TYPE_ID"="A"."CALL_TYPE_ID")
34 - access("L"."TEAM_ID"(+)="A"."LAST_ACTION_TEAM")
36 - access("I"."APPL_ID"(+)="A"."APPL_ID" AND "I"."ENV_ID"(+)="A"."ENV_ID")
38 - access("E"."APPL_ID"="A"."APPL_ID" AND "E"."MODULE_ID"="A"."MODULE_ID")
40 - access("C"."CODE"="A"."ORGID")
42 - access("K"."USER_NAME"(+)="A"."LAST_ACTION_USER")
44 - access("B"."USER_NAME"(+)="A"."CALLER_ID")
46 - access("G"."USER_NAME"(+)="A"."UPDUSERID")
48 - access("LU"."USER_NAME"(+)=NVL("SYS_ALIAS_4"."UPDUSERID_162","SYS_ALIAS_4"."UPDUSERID_25"))
65 - filter( EXISTS (SELECT /*+ */ 0 FROM "LCC"."VHD_CALLDESK_HISTORY" "Q" WHERE "Q"."CALL_ID"=:B1
"Q"."CALL_ID" HAVING MIN("Q"."UPDDATE")=:B2))
67 - access("SYS_ALIAS_2"."CALL_ID"="SYS_ALIAS_1"."CALL_ID")
68 - filter(MIN("Q"."UPDDATE")=:B1)
71 - access("Q"."CALL_ID"=:B1)
73 - access("H"."MODE_ID"(+)="SYS_ALIAS_1"."MODE_ID")
75 - access("D"."APPL_ID"="SYS_ALIAS_1"."APPL_ID")
77 - access("F"."CALL_TYPE_ID"="SYS_ALIAS_1"."CALL_TYPE_ID")
79 - access("L"."TEAM_ID"(+)=TO_NUMBER("SYS_ALIAS_1"."LAST_ACTION_USER"))
81 - access("I"."APPL_ID"(+)="SYS_ALIAS_1"."APPL_ID" AND "I"."ENV_ID"(+)="SYS_ALIAS_1"."ENV_ID")
83 - access("E"."APPL_ID"="SYS_ALIAS_1"."APPL_ID" AND "E"."MODULE_ID"="SYS_ALIAS_1"."MODULE_ID")
85 - access("SYS_ALIAS_1"."ORGID"="J"."ORGID" AND "J"."TREE"='HLPDK')
87 - access("C"."CODE"="SYS_ALIAS_1"."ORGID")
89 - access("B"."USER_NAME"(+)="SYS_ALIAS_1"."CALLER_ID")
91 - access("SYS_ALIAS_1"."UPDUSERID"="G"."USER_NAME"(+))
93 - access("K"."USER_NAME"(+)="SYS_ALIAS_1"."LAST_ACTION_USER")
95 - access("LU"."USER_NAME"(+)=NVL("SYS_ALIAS_3"."UPDUSERID_162","SYS_ALIAS_3"."UPDUSERID_25"))
Note: cpu costing is offI've tried to look thru your sql and changed it a bit. Of course not testet :-)
Your problem isn't the archive table! I tried to remove the 2 selects from the select-clause. Furthermore you have a lot of nested loops in your explain, which is a performance-killer. Try getting rid of them, perhaps use /*+ USE_HASH(?,?) */.
SELECT a.call_id, a.entry_date,
NVL (INITCAP (b.full_name), caller_name) AS caller_name, c.description AS org_desc, a.env_id, i.env_desc, a.appl_id,
d.appl_desc, a.module_id, e.module_desc, a.call_type_id, f.call_type_desc, a.priority, a.upduserid,
INITCAP (g.full_name) AS lastupdated_username, a.call_desc, h.mode_desc, a.received_time, a.assignment_team, a.status,
ROUND (lcc.pkg_com.fn_datediff ('MI', a.entry_date, a.status_date)) AS elapsed_time,
ROUND (lcc.pkg_com.fn_datediff ('MI', a.entry_date, a.status_date)) AS resolved_min,
CASE
WHEN a.orgid IN (1, 100, 200)
THEN a.orgid
ELSE j.regionorgid
END AS region,
COALESCE (stat.upddate, a.upddate) AS stat_upddate,
t.team_desc, a.eta_date,
COALESCE (a.caller_contact, b.telephone) AS caller_contact,
COALESCE (a.caller_email, b.email) AS email, a.affected_users,
a.outage_time, a.qa_done, a.last_action_team, a.last_action_user,
INITCAP (k.full_name) AS last_action_username, a.last_action_date,
l.team_desc AS last_action_teamdesc, a.refid,
INITCAP (lu.full_name) AS logged_name, a.pmreview,
a.status AS main_status
FROM lcc.vhd_calldesk_archive a, lcc.lcc_userinfo_details b, lcc.com_organization c,
lcc.vhd_applications d, lcc.vhd_modules e, lcc.vhd_calltypes f, lcc.com_rptorganization j,
lcc.lcc_userinfo_details g, lcc.vhd_callmode h, lcc.vhd_environment i, lcc.lcc_userinfo_details k,
lcc.vhd_teams l,
(SELECT call_id, upduserid
FROM lcc.vhd_calldesk_history p
WHERE upddate IN (SELECT MIN (upddate)
FROM lcc.vhd_calldesk_history q
WHERE q.call_id = p.call_id
GROUP BY call_id)) ku,
lcc.lcc_userinfo_details lu,
(SELECT call_id, MAX (upddate)
FROM lcc.vhd_callstatus
GROUP BY call_id) stat,
lcc.vhd_teams t
WHERE a.caller_id = b.user_name(+)
AND a.orgid = c.code
AND a.appl_id = d.appl_id
AND a.appl_id = e.appl_id
AND a.module_id = e.module_id
AND a.call_type_id = f.call_type_id
AND a.orgid = j.orgid
AND j.tree = 'HLPDK'
AND a.upduserid = g.user_name(+)
AND a.mode_id = h.mode_id(+)
AND a.appl_id = i.appl_id(+)
AND a.env_id = i.env_id(+)
AND a.last_action_user = k.user_name(+)
AND a.last_action_user = l.team_id(+)
AND a.call_id = ku.call_id(+)
AND NVL (ku.upduserid, a.upduserid) = lu.user_name(+)
AND a.call_id = stat.call_id
AND a.assignment_team = t.team_id; -
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. -
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 -
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. -
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). -
I can't use this query on 10G, but can use on 9i
I have ever used bellow query and no error
SQL>select so.* from bsowner.sales_orders so left join bsowner.relation_address rla on (so.customerid = rla.relationid and so.delivery_addressid = rla.addressid ) and rla.addresstype = (select code from bsowner.tab_addtyp where config1=3)
When I use on 10G, I can't query
1* select so.* from bsowner.sales_orders so left join bsowner.relation_address rla on (so.customerid = rla.relationid and so.delivery_addressid = rla.addressid ) and rla.addresstype = (select code from bsowner.tab_addtyp where config1=3)
SQL> /
select so.* from bsowner.sales_orders so left join bsowner.relation_address rla on (so.customerid = rla.relationid and so.delivery_addressid = rla.addressid ) and rla.addresstype = (select code from bsowner.tab_addtyp where config1=3)
ERROR at line 1:
ORA-01799: a column may not be outer-joined to a subquery
Help me,Please
Why I can't use this on 10G?
when i change = to in , i can use
but i don't want to change
help me for the reasonI don't this gonna work on 9i either.
Chang your query to
select so.* from bsowner.sales_orders so left join bsowner.relation_address rla on (so.customerid = rla.relationid and so.delivery_addressid = rla.addressid )
Where
rla.addresstype = (select code from bsowner.tab_addtyp where config1=3) -
Can you please explain how this query is fetching the rows?
here is a query to find the top 3 salaries. But the thing is that i am now able to understand how its working to get the correct data :How the data in the alias table P1 and P2 getting compared. Can you please explain in some steps.
SELECT MIN(P1.SAL) FROM PSAL P1, PSAL P2
WHERE P1.SAL >= P2.SAL
GROUP BY P2.SAL
HAVING COUNT (DISTINCT P1.SAL) <=3 ;
here is the data i used :
SQL> select * from psal;
NAME SAL
able 1000
baker 900
charles 900
delta 800
eddy 700
fred 700
george 700
george 700
Regards,
Renu... Please help me in understanding the query.
Your query looks like anything but a Top-N query.
If you run it in steps and analyze the output at the end of each step, then you should be able to understand what it does.
Given below is some brief information on the same:
test@ora>
test@ora> --
test@ora> -- Query 1 - using the non-equi (theta) join
test@ora> --
test@ora> with psal as (
2 select 'able' as name, 1000 as sal from dual union all
3 select 'baker', 900 from dual union all
4 select 'charles', 900 from dual union all
5 select 'delta', 800 from dual union all
6 select 'eddy', 700 from dual union all
7 select 'fred', 700 from dual union all
8 select 'george', 700 from dual union all
9 select 'george', 700 from dual)
10 --
11 SELECT p1.sal AS p1_sal, p1.NAME AS p1_name, p2.sal AS p2_sal,
12 p2.NAME AS p2_name
13 FROM psal p1, psal p2
14 WHERE p1.sal >= p2.sal;
P1_SAL P1_NAME P2_SAL P2_NAME
1000 able 1000 able
1000 able 900 baker
1000 able 900 charles
1000 able 800 delta
1000 able 700 eddy
1000 able 700 fred
1000 able 700 george
1000 able 700 george
900 baker 900 baker
900 baker 900 charles
900 baker 800 delta
900 baker 700 eddy
900 baker 700 fred
900 baker 700 george
900 baker 700 george
900 charles 900 baker
900 charles 900 charles
900 charles 800 delta
900 charles 700 eddy
900 charles 700 fred
900 charles 700 george
900 charles 700 george
800 delta 800 delta
800 delta 700 eddy
800 delta 700 fred
800 delta 700 george
800 delta 700 george
700 eddy 700 eddy
700 eddy 700 fred
700 eddy 700 george
700 eddy 700 george
700 fred 700 eddy
700 fred 700 fred
700 fred 700 george
700 fred 700 george
700 george 700 eddy
700 george 700 fred
700 george 700 george
700 george 700 george
700 george 700 eddy
700 george 700 fred
700 george 700 george
700 george 700 george
43 rows selected.
test@ora>
test@ora>This query joins PSAL with itself using a non equi-join. Take each row of PSAL p1 and see how it compares with PSAL p2. You'll see that:
- Row 1 with sal 1000 is >= to all sal values of p2, so it occurs 8 times
- Row 2 with sal 900 is >= to 9 sal values of p2, so it occurs 7 times
- Row 3: 7 times again... and so on.
- So, total no. of rows are: 8 + 7 + 7 + 5 + 4 + 4 + 4 + 4 = 43
test@ora>
test@ora> --
test@ora> -- Query 2 - add the GROUP BY
test@ora> --
test@ora> with psal as (
2 select 'able' as name, 1000 as sal from dual union all
3 select 'baker', 900 from dual union all
4 select 'charles', 900 from dual union all
5 select 'delta', 800 from dual union all
6 select 'eddy', 700 from dual union all
7 select 'fred', 700 from dual union all
8 select 'george', 700 from dual union all
9 select 'george', 700 from dual)
10 --
11 SELECT p2.sal AS p2_sal,
12 COUNT(*) as cnt,
13 COUNT(p1.sal) as cnt_p1_sal,
14 COUNT(DISTINCT p1.sal) as cnt_dist_p1_sal,
15 MIN(p1.sal) as min_p1_sal,
16 MAX(p1.sal) as max_p1_sal
17 FROM psal p1, psal p2
18 WHERE p1.sal >= p2.sal
19 GROUP BY p2.sal;
P2_SAL CNT CNT_P1_SAL CNT_DIST_P1_SAL MIN_P1_SAL MAX_P1_SAL
700 32 32 4 700 1000
800 4 4 3 800 1000
900 6 6 2 900 1000
1000 1 1 1 1000 1000
test@ora>
test@ora>Now, if you group by p2.sal in the output of query 1, and check the number of distinct p1.sal, min of p1.sal etc. you see that for p2.sal values - 800, 900 and 1000, there are 3 or less p1.sal values associated.
So, the last 3 rows are the ones you are interested in, essentially. As follows:
test@ora>
test@ora> --
test@ora> -- Query 3 - GROUP BY and HAVING
test@ora> --
test@ora> with psal as (
2 select 'able' as name, 1000 as sal from dual union all
3 select 'baker', 900 from dual union all
4 select 'charles', 900 from dual union all
5 select 'delta', 800 from dual union all
6 select 'eddy', 700 from dual union all
7 select 'fred', 700 from dual union all
8 select 'george', 700 from dual union all
9 select 'george', 700 from dual)
10 --
11 SELECT p2.sal AS p2_sal,
12 COUNT(*) as cnt,
13 COUNT(p1.sal) as cnt_p1_sal,
14 COUNT(DISTINCT p1.sal) as cnt_dist_p1_sal,
15 MIN(p1.sal) as min_p1_sal,
16 MAX(p1.sal) as max_p1_sal
17 FROM psal p1, psal p2
18 WHERE p1.sal >= p2.sal
19 GROUP BY p2.sal
20 HAVING COUNT(DISTINCT p1.sal) <= 3;
P2_SAL CNT CNT_P1_SAL CNT_DIST_P1_SAL MIN_P1_SAL MAX_P1_SAL
800 4 4 3 800 1000
900 6 6 2 900 1000
1000 1 1 1 1000 1000
test@ora>
test@ora>
test@ora>That's what you are doing in that query.
The thing is - in order to find out Top-N values, you simply need to scan that one table PSAL. So, joining it to itself is not necessary.
A much simpler query is as follows:
test@ora>
test@ora>
test@ora> --
test@ora> -- Top-3 salaries - distinct or not; using ROWNUM on ORDER BY
test@ora> --
test@ora> with psal as (
2 select 'able' as name, 1000 as sal from dual union all
3 select 'baker', 900 from dual union all
4 select 'charles', 900 from dual union all
5 select 'delta', 800 from dual union all
6 select 'eddy', 700 from dual union all
7 select 'fred', 700 from dual union all
8 select 'george', 700 from dual union all
9 select 'george', 700 from dual)
10 --
11 SELECT sal
12 FROM (
13 SELECT sal
14 FROM psal
15 ORDER BY sal DESC
16 )
17 WHERE rownum <= 3;
SAL
1000
900
900
test@ora>
test@ora>
test@ora>And for Top-3 distinct salaries:
test@ora>
test@ora> --
test@ora> -- Top-3 DISTINCT salaries; using ROWNUM on ORDER BY on DISTINCT
test@ora> --
test@ora> with psal as (
2 select 'able' as name, 1000 as sal from dual union all
3 select 'baker', 900 from dual union all
4 select 'charles', 900 from dual union all
5 select 'delta', 800 from dual union all
6 select 'eddy', 700 from dual union all
7 select 'fred', 700 from dual union all
8 select 'george', 700 from dual union all
9 select 'george', 700 from dual)
10 --
11 SELECT sal
12 FROM (
13 SELECT DISTINCT sal
14 FROM psal
15 ORDER BY sal DESC
16 )
17 WHERE rownum <= 3;
SAL
1000
900
800
test@ora>
test@ora>
test@ora>You may also want to check out the RANK and DENSE_RANK analytic functions.
RANK:
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions123.htm#SQLRF00690
DENSE_RANK:
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions043.htm#SQLRF00633
HTH
isotope -
How Can i add "DateDiff(day, T0.DueDate" as a column in this query?
How Can i add "DateDiff(day, T0.DueDate" as a column in this query?
SELECT T1.CardCode, T1.CardName, T1.CreditLine, T0.RefDate, T0.Ref1 'Document Number',
CASE WHEN T0.TransType=13 THEN 'Invoice'
WHEN T0.TransType=14 THEN 'Credit Note'
WHEN T0.TransType=30 THEN 'Journal'
WHEN T0.TransType=24 THEN 'Receipt'
END AS 'Document Type',
T0.DueDate, (T0.Debit- T0.Credit) 'Balance'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')<=-1),0) 'Future'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')>=0 and DateDiff(day, T0.DueDate,'[%1]')<=30),0) 'Current'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')>30 and DateDiff(day, T0.DueDate,'[%1]')<=60),0) '31-60 Days'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')>60 and DateDiff(day, T0.DueDate,'[%1]')<=90),0) '61-90 Days'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')>90 and DateDiff(day, T0.DueDate,'[%1]')<=120),0) '91-120 Days'
,ISNULL((SELECT T0.Debit-T0.Credit WHERE DateDiff(day, T0.DueDate,'[%1]')>=121),0) '121+ Days'
FROM JDT1 T0 INNER JOIN OCRD T1 ON T0.ShortName = T1.CardCode
WHERE (T0.MthDate IS NULL OR T0.MthDate > [%1]) AND T0.RefDate <= [%1] AND T1.CardType = 'C'
ORDER BY T1.CardCode, T0.DueDate, T0.Ref1Hi,
As you mentioned not possible to assign the dynamic column in the query.
will give you example for generate a dynamic column name in SQL query, using this example you can achieve your requirement.
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(C.Name)
from [History]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT [Date],' + @cols +'
from
select [Date], Name, Value
from [History]
) x
pivot
max(value)
for Name in (' + @cols + ')
) p '
execute(@query)
Maybe you are looking for
-
Creating Dynamic Column Names at Runtime
I have a dynamic query that I'm running under Portal. I would like to assign column headings based on the query results. Example: Select a.x "a.name_x", a.y "a.name_y", a.z "a.name_z" from a where a.q = "user input" I know the above example will not
-
Error in posting when transfer to a new personnel area / company code
Dear Experts, We have a scenario where we have a transfer action for some of employees to a new personnel area (also new company code). When we post the result to accounting, we have an error like this : "Company code clearing account not found in c
-
Selling Macbook and erasing and restoring to Lion. Am I on the right track?
Hi All, I'm planning to sell a Macbook from 2008 that originally came with Snow Leopard. I have since upgraded it to Lion. I've read the discussions and I think I'm on the right track. So far, I restarted and held the command and R keys. That b
-
LDAP: error code 53 - 0000055E: SvcErr: DSID-031A0FC0, problem 5003
Hi, I Am trying to add an User(whose Primary Group is'Domian users') to a Group called "CN=DS_Disabled_IG,OU=Common,OU=Access Management,OU=Security Groups,OU=BAND,dc=something,DC=com" by using the below code: LdapContext ctx = null; ctx = new Initia
-
Sensirion EKP-3 Code to read the raw ticks from the SDP6xx Pressure Transducer with LabVIEW
Guys: I have seen the post here about the Temp Humidity sensor: Ref: http://forums.ni.com/t5/forums/replypage/board-id/170/message-id/749141 Pardon the post under a new topic but I was advised to post it in a "new thread"... With the Device name in t