Help - tuning analytic functions
Where can I find information on hints to speed up oracle analytic functions?
The table xyz has about 12 million rows.
The col1 / col2 combinations are effective dated and have an Active /Inactive status.
Table xyz: col1, col2, effdt, status.
Goal: I want to eliminate the col1 / col2 combinations where all rows over time have an Inactive status.
The sq I wrote looks like this:
select * from
select col1, col2,
SUM (1) OVER (PARTITION BY f.col1, f.col2 ORDER BY fcol1, f.col2) total_cnt,
SUM (CASE WHEN f.status = 'I' THEN 1 ELSE 0 END) OVER
(PARTITION BY f.col1, f.col2 ORDER BY f.col1) inactive_cnt
from table xyz f
where total_cnt > inactive_cnt
Thanks,
Frank
Have a look at these standard threads:
How to post a tuning request:
HOW TO: Post a SQL statement tuning request - template posting
When your query takes too long:
When your query takes too long ...
Similar Messages
-
I successfully use the following analytical function to sum all net_movement of a position (key for a position: bp_id, prtfl_num, instrmnt_id, cost_prc_crncy) from first occurrence until current row:
SELECT SUM (net_movement) OVER (PARTITION BY bp_id, prtfl_num, instrmnt_id, cost_prc_crncy ORDER BY TRUNC (val_dt) RANGE BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING) holding,
what i need is another column to sum net_movement of a position but only for the current date, but all my approaches fail..
- add the date (val_dt) to the 'partition by' clause and therefore sum only values with same position and date
SELECT SUM (net_movement) OVER (PARTITION BY val_dt, bp_id, prtfl_num, instrmnt_id, cost_prc_crncy ORDER BY TRUNC (val_dt) RANGE BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING) today_net_movement
- take the holding for the last date and subtract it from the current holding afterwards
SELECT SUM (net_movement) OVER (PARTITION BY bp_id, prtfl_num, instrmnt_id, cost_prc_crncy ORDER BY TRUNC (val_dt) RANGE BETWEEN UNBOUNDED PRECEDING AND -1 FOLLOWING) last_holding,
- using lag on the analytical function which calculates holding fails too
I also want to avoid creating a table which stores the last holding..
Does anyone sees where I make a mistake or knows an alternative to get this value?
It would help me much!
Thanks in advance!Thank you,
but I already tried that but it returns strange values which are not the correct ones for sure.
It is always the same value for each row, if its not 0, and a very high one (500500 for example), even if the sum of all net_movement of that date is 0 (and the statement for holding returns 0 too)
I also tried witch trunc(val_dt,'DDD') with the same result (without trunc it is the same issue)
please help if you can, thanks in advance! -
I need help with Analytic Function
Hi,
I have this little problem that I need help with.
My datafile has thousands of records that look like...
Client_Id Region Countries
[1] [1] [USA, Canada]
[1] [2] [Australia, France, Germany]
[1] [3] [China, India, Korea]
[1] [4] [Brazil, Mexico]
[8] [1] [USA, Canada]
[9] [1] [USA, Canada]
[9] [4] [Argentina, Brazil]
[13] [1] [USA, Canada]
[15] [1] [USA]
[15] [4] [Argentina, Brazil]
etc
My task is is to create a report with 2 columns - Client_Id and Countries, to look something like...
Client_Id Countries
[1] [USA, Canada, Australia, France, Germany, China, India, Korea, Brazil, Mexico]
[8] [USA, Canada]
[9] [USA, Canada, Argentina, Brazil]
[13] [USA, Canada]
[15] [USA, Argentina, Brazil]
etc.
How can I achieve this using Analytic Function(s)?
Thanks.
BDFHi,
That's called String Aggregation , and the following site shows many ways to do it:
http://www.oracle-base.com/articles/10g/StringAggregationTechniques.php
Which one should you use? That depends on which version of Oracle you're using, and your exact requirements.
For example, is order importatn? You said the results shoudl include:
CLIENT_ID COUNTRIES
1 USA, Canada, Australia, France, Germany, China, India, Korea, Brazil, Mexicobut would you be equally happy with
CLIENT_ID COUNTRIES
1 Australia, France, Germany, China, India, Korea, Brazil, Mexico, USA, Canadaor
CLIENT_ID COUNTRIES
1 Australia, France, Germany, USA, Canada, Brazil, Mexico, China, India, Korea?
Mwalimu wrote:
... How can I achieve this using Analytic Function(s)?The best solution may not involve analytic functions at all. Is that okay?
If you'd like help, post your best attempt, a little sample data (CREATE TABLE and INSERT statements), the results you want from that data, and an explanation of how you get those results from that data.
Always say which version of Oracle you're using.
Edited by: Frank Kulash on Aug 29, 2011 3:05 PM -
Help with analytical function (ora 9...)
Hi everyone, is there a way to fill some missing numbers based on what have come before and after that missing number by starttime and based on how many missing data are between? ... by "simple" select? I know how to do that just theoreticly with simple math commands, but is there a way to apply them in sql (analytical functions)?
Thanks in advance for any ideas !
The missing number on line 17 could be calculated as 339+(1/2)*(356-339) = 347,5
The missing number on line 23 could be calculated as 355+(1/3)*(292-355) = 334
The missing number on line 24 could be calculated as 355+(2/3)*(292-355) = 313
rownumber + temp_table (starttime,data_column)
15 23.5.2007 16:15 , 258
16 23.5.2007 16:30 , 339
17 23.5.2007 16:45 ,
18 23.5.2007 17:00 , 356
19 23.5.2007 17:15 , 373
20 23.5.2007 17:30 , 355
21 23.5.2007 17:45 , 363
22 23.5.2007 18:00 , 355
23 23.5.2007 18:15 ,
24 23.5.2007 18:30 ,
25 23.5.2007 19:00 , 292
26 23.5.2007 19:15 , 295
THANKS
Message was edited by:
dusooWay too late, but I wouldn't let my effort go unpublished ;-)
SQL> create table temp_table
2 as
3 select 15 rownumber, to_date('23.5.2007 16:15','dd.mm.yyyy hh24:mi') starttime, 258 data_column from dual union all
4 select 16, to_date(' 23.5.2007 16:30','dd.mm.yyyy hh24:mi'), 339 from dual union all
5 select 17, to_date(' 23.5.2007 16:45','dd.mm.yyyy hh24:mi'), null from dual union all
6 select 18, to_date(' 23.5.2007 17:00','dd.mm.yyyy hh24:mi'), 356 from dual union all
7 select 19, to_date(' 23.5.2007 17:15','dd.mm.yyyy hh24:mi'), 373 from dual union all
8 select 20, to_date(' 23.5.2007 17:30','dd.mm.yyyy hh24:mi'), 355 from dual union all
9 select 21, to_date(' 23.5.2007 17:45','dd.mm.yyyy hh24:mi'), 363 from dual union all
10 select 22, to_date(' 23.5.2007 18:00','dd.mm.yyyy hh24:mi'), 355 from dual union all
11 select 23, to_date(' 23.5.2007 18:15','dd.mm.yyyy hh24:mi'), null from dual union all
12 select 24, to_date(' 23.5.2007 18:30','dd.mm.yyyy hh24:mi'), null from dual union all
13 select 25, to_date(' 23.5.2007 19:00','dd.mm.yyyy hh24:mi'), 292 from dual union all
14 select 26, to_date(' 23.5.2007 19:15','dd.mm.yyyy hh24:mi'), 295 from dual
15 /
Tabel is aangemaakt.
SQL> with t as
2 ( select t.*
3 , max(case when data_column is not null then rownumber end) over (order by rownumber) lowerbound
4 , last_value(data_column ignore nulls) over (order by rownumber) prevvalue
5 , min(case when data_column is not null then rownumber end) over (order by rownumber desc) upperbound
6 , last_value(data_column ignore nulls) over (order by rownumber desc) nextvalue
7 from temp_table t
8 )
9 select rownumber
10 , starttime
11 , case
12 when data_column is not null then data_column
13 else prevvalue * ((upperbound - rownumber) / (upperbound - lowerbound))
14 + nextvalue * ((rownumber - lowerbound) / (upperbound - lowerbound))
15 end data_column
16 from t
17 order by rownumber
18 /
ROWNUMBER STARTTIME DATA_COLUMN
15 23-05-2007 16:15:00 258
16 23-05-2007 16:30:00 339
17 23-05-2007 16:45:00 347,5
18 23-05-2007 17:00:00 356
19 23-05-2007 17:15:00 373
20 23-05-2007 17:30:00 355
21 23-05-2007 17:45:00 363
22 23-05-2007 18:00:00 355
23 23-05-2007 18:15:00 334
24 23-05-2007 18:30:00 313
25 23-05-2007 19:00:00 292
26 23-05-2007 19:15:00 295
12 rijen zijn geselecteerd.Regards,
Rob. -
Hello Everybody,
I have a table called test
Create table test (col1 number,col2 varchar2(20),col3 varchar2(20));
Insert into test values(1,’A’,’PER1’)
Insert into test values(2,’A’,’PER1’)
Insert into test values(3,’A’,’PER1’)
Insert into test values(1,’A’,’PER2’)
Insert into test values(2,’B’,’PER2’)
Expected result is
Distinct count of col1 based on col2 and the output for each period
Eg
For ‘A’ type record count = 3 for ‘PER1’
For ‘B’ type record count =1 for ‘PER2’
This is because col1=1 is in both ‘A’ type and ‘B’ type record
Expected Output should be like this
Type Period Count
‘A’ ‘PER1’ 3
‘B’ ‘PER2’ 1
Thanks,
Jeeva.Hi Anurag,
SELECT DISTINCT *
FROM (SELECT 100,
'CARS', user
'COMBINED',
decode(credit_amt,0,'D','C') dr_cr_ind,
a.acct_type_code acct_type_code,
COUNT (DISTINCT a.merchant_num)
OVER (PARTITION BY a.acct_type_code,decode(credit_amt,0,'D','C'))
tot_mer_count,
SUM (b.debit_amt)
OVER (PARTITION BY a.acct_type_code, decode(DEBIT_amt,0,'C','D'),to_char(b.acct_date,'MM/YYYY'))
sum_db,
SUM (b.credit_amt)
OVER (PARTITION BY a.acct_type_code, decode(credit_amt,0,'D','C'),to_char(b.acct_date,'MM/YYYY'))
sum_cb,
SUM (1) OVER (PARTITION BY a.acct_type_code,decode(credit_amt,0,'D','C'),to_char(b.acct_date,'MM/YYYY'))
cnt_trans
,to_char(b.acct_date,'MM/YYYY') ACCT_DATE
FROM merchant a,
merchant_transactions c,
fo_oracle_gl b
WHERE a.merchant_num = c.merchant_num
AND a.merchant_num = b.merchant_num
AND a.acct_type_code IN
('FRAUD', 'BANK', 'NORM', 'RES', 'PRECO')
AND a.clearing_bank_code IN ('BBOS')
AND ( (b.debit_amt > 0
AND c.transaction_type NOT IN
('ECF', 'ACF', 'ACHECF', 'ACHACF', 'WSTJRNLDRM'))
OR (b.credit_amt > 0
AND c.transaction_type NOT IN
('DISFEECOL',
'MICFEECOL',
'PROCFEECOL',
'TELFEECOL',
'MICCOLAUTO',
'TELCOLAUTO',
'TMCOLAUTO',
'DISCOLAUTO',
'TMFEECOL',
'ECFWV',
'ECFWO',
'ACFWV',
'ACFWO',
'WSTJRNLCRM',
'MSIWOFFCRM')))
AND c.transaction_ref = b.rpt_incoming_txn_ref
AND b.acct_date BETWEEN TO_DATE ('12/15/2008', 'mm/dd/yyyy')
AND TO_DATE ('12/14/2009', 'mm/dd/yyyy')
AND b.impacted_balance_ind IN ('L')
AND b.plus_zero_minus_ind <> 0
AND NOT ( (b.cars_transaction_type = 'WOFF')
OR ( b.credit_amt > 0
AND b.impacted_balance_ind = 'L'
AND b.rpt_txn_ref = b.rpt_incoming_txn_ref)
OR (b.debit_amt > 0 AND b.impacted_balance_ind = 'A'))) In the above query this tot_mer_count columns identifies the total debit and credit transactions for each account type. Now i am supposed to get the actual count for the specified periods like 01/jan/2009 to 14/dec/2009. This date wiil vary based on the parameter.
this single query give values for 3 date range like , full year(which the above query will give) , full month, and the date range they specify in the parameter (date range will be within the resultset)
My idea is to get the distinct of merchant count for each and every period so that while reporting i can sum based on date range.
Please note. the constraint is if mer1 did a transaction in period 1 and did another transaction in period 2 he should not be counted again. Here we are trying to get the count of merchants involved in trading not the no of transaction they made.
Thanks for your help and time,
Jeeva.
Edited by: user12128516 on Dec 15, 2009 10:34 AM -
Hello.
I am not used to anaylitic funtions and after reading a lot about them I am very confused.
I have a situation similar to the test_table I post below, I have a table with 2 columns event_code (number) and event_date (date) which make the primary key. I need to see all the event_code's and event_date's of the table, I also need to compare the columns value1 and value2 so that if value1>value2 and event_date for that record belongs to september of 2008 it takes the value 1 (0 otherwise):
WITH test_table AS
(SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -3) event_date, 1 value1,
1 value2
FROM DUAL
UNION
SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -2) event_date, 3 value1,
2 value2
FROM DUAL
UNION
SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -4) event_date,
100 value1, -1 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -3) event_date,
122 value1, 1 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -2) event_date,
133 value1, -4 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -1) event_date,
1454 value1, 1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -3) event_date,
125 value1, 1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -2) event_date,
1888 value1, -1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -1) event_date,
144 value1, 1 value2
FROM DUAL)
SELECT event_code, event_date, value1, value2,
CASE
WHEN ( (value1 > value2) AND (event_date BETWEEN TO_DATE ('09/01/2008 00:00:00','mm/dd/yyyy hh24:mi:ss') AND TO_DATE ('09/30/2008 23:59:59','mm/dd/yyyy hh24:mi:ss')))
THEN 1
ELSE 0
END bigger
FROM test_table
EVENT_CODE EVENT_DA VALUE1 VALUE2 BIGGER
1 20/06/08 100 -1 0
1 20/07/08 1 1 0
1 20/08/08 3 2 0
2 19/07/08 122 1 0
2 19/08/08 133 -4 0
2 19/09/08 1454 1 1
3 18/07/08 125 1 0
3 18/08/08 1888 -1 0
3 18/09/08 144 1 1
9 rows selected.Finally and here comes my problem, I need to see, for each row, the maximun date for the event_code of the row whenever that maximun date belongs to september of 2008 (null otherwise), I have not been able to write that, this is the result I need to see:
EVENT_CODE EVENT_DATE VALUE1 VALUE2 BIGGER LAST_DATE
1 20/06/08 100 -1 0
1 20/07/08 1 1 0
1 20/08/08 3 2 0
2 19/07/08 122 1 0 19/09/08
2 19/08/08 133 -4 0 19/09/08
2 19/09/08 1454 1 1 19/09/08
3 18/07/08 125 1 0 18/09/08
3 18/08/08 1888 -1 0 18/09/08
3 18/09/08 144 1 1 18/09/08
9 rows selected.And this is my try (wrong):
/* Formatted on 2008/10/21 10:48 (Formatter Plus v4.8.8) */
WITH test_table AS
(SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -3) event_date, 1 value1,
1 value2
FROM DUAL
UNION
SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -2) event_date, 3 value1,
2 value2
FROM DUAL
UNION
SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -4) event_date,
100 value1, -1 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -3) event_date,
122 value1, 1 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -2) event_date,
133 value1, -4 value2
FROM DUAL
UNION
SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -1) event_date,
1454 value1, 1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -3) event_date,
125 value1, 1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -2) event_date,
1888 value1, -1 value2
FROM DUAL
UNION
SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -1) event_date,
144 value1, 1 value2
FROM DUAL)
SELECT event_code, event_date, value1, value2,
CASE
WHEN ( (value1 > value2) AND (event_date BETWEEN TO_DATE ('09/01/2008 00:00:00','mm/dd/yyyy hh24:mi:ss') AND TO_DATE ('09/30/2008 23:59:59','mm/dd/yyyy hh24:mi:ss')))
THEN 1
ELSE 0
END bigger,
LAST_VALUE (event_date) OVER (PARTITION BY event_code ORDER BY event_date range between TO_DATE ('09/01/2008 00:00:00','mm/dd/yyyy hh24:mi:ss') PRECEDING and TO_DATE ('09/30/2008 23:59:59','mm/dd/yyyy hh24:mi:ss') FOLLOWING ) last_date
FROM test_tableThanks in advance.I have added a new column to my test_table value3 (number) and I need to see, for each row the value that that column has when it is in the record with has event_date=last_date for each code.
I have tried this:
SQL> r
1 WITH test_table AS
2 (SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -3) event_date, 1 value1,
3 1 value2, 9 value3
4 FROM DUAL
5 UNION ALL
6 SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -2) event_date, 3 value1,
7 2 value2, 8 value3
8 FROM DUAL
9 UNION ALL
10 SELECT 1 event_code, ADD_MONTHS (SYSDATE - 1, -4) event_date,
11 100 value1, -1 value2, 7 value3
12 FROM DUAL
13 UNION ALL
14 SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -3) event_date,
15 122 value1, 1 value2, 6 value3
16 FROM DUAL
17 UNION ALL
18 SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -2) event_date,
19 133 value1, -4 value2, 5 value3
20 FROM DUAL
21 UNION ALL
22 SELECT 2 event_code, ADD_MONTHS (SYSDATE - 2, -1) event_date,
23 1454 value1, 1 value2, 4 value3
24 FROM DUAL
25 UNION ALL
26 SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -3) event_date,
27 125 value1, 1 value2, 3 value3
28 FROM DUAL
29 UNION ALL
30 SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -2) event_date,
31 1888 value1, -1 value2, 2 value3
32 FROM DUAL
33 UNION ALL
34 SELECT 3 event_code, ADD_MONTHS (SYSDATE - 3, -1) event_date,
35 144 value1, 1 value2, 1 value3
36 FROM DUAL)
37 SELECT event_code, event_date, value1, value2, value3,
38 CASE
39 WHEN ( (value1 > value2)
40 AND (event_date BETWEEN TO_DATE ('09/01/2008 00:00:00',
41 'mm/dd/yyyy hh24:mi:ss'
42 )
43 AND TO_DATE ('09/30/2008 23:59:59',
44 'mm/dd/yyyy hh24:mi:ss'
45 )
46 )
47 )
48 THEN 1
49 ELSE 0
50 END bigger,
51 CASE
52 WHEN MAX (event_date) OVER (PARTITION BY event_code)
53 BETWEEN TO_DATE ('09/01/2008 00:00:00',
54 'mm/dd/yyyy hh24:mi:ss'
55 )
56 AND TO_DATE ('09/30/2008 23:59:59',
57 'mm/dd/yyyy hh24:mi:ss'
58 )
59 THEN MAX (event_date) OVER (PARTITION BY event_code)
60 ELSE NULL
61 END last_date,
62 CASE
63 WHEN MAX (event_date) OVER (PARTITION BY event_code)
64 BETWEEN TO_DATE ('09/01/2008 00:00:00',
65 'mm/dd/yyyy hh24:mi:ss'
66 )
67 AND TO_DATE ('09/30/2008 23:59:59',
68 'mm/dd/yyyy hh24:mi:ss'
69 )
70 THEN LAST_VALUE (value3) OVER (PARTITION BY event_code ORDER BY event_date)
71 ELSE NULL
72 END last_value3
73 FROM test_table
74* ORDER BY 1, 2
EVENT_CODE EVENT_DA VALUE1 VALUE2 VALUE3 BIGGER LAST_DAT LAST_VALUE3
1 20/06/08 100 -1 7 0
1 20/07/08 1 1 9 0
1 20/08/08 3 2 8 0
2 19/07/08 122 1 6 0 19/09/08 6
2 19/08/08 133 -4 5 0 19/09/08 5
2 19/09/08 1454 1 4 1 19/09/08 4
3 18/07/08 125 1 3 0 18/09/08 3
3 18/08/08 1888 -1 2 0 18/09/08 2
3 18/09/08 144 1 1 1 18/09/08 1
9 rows selected.But what I want is (I am sorry for my ignorance but I don't unerstand why the "ORDER BY event_date" "breaks" my "PARTITION BY event_code"):
EVENT_CODE EVENT_DA VALUE1 VALUE2 VALUE3 BIGGER LAST_DAT LAST_VALUE3
1 20/06/08 100 -1 7 0
1 20/07/08 1 1 9 0
1 20/08/08 3 2 8 0
2 19/07/08 122 1 6 0 19/09/08 4
2 19/08/08 133 -4 5 0 19/09/08 4
2 19/09/08 1454 1 4 1 19/09/08 4
3 18/07/08 125 1 3 0 18/09/08 1
3 18/08/08 1888 -1 2 0 18/09/08 1
3 18/09/08 144 1 1 1 18/09/08 1Thanks again. -
Need Help in analytic function (LAG)
The requirement is like I have a table with belwo colums
col1 count flag flag2
abc 1 Y Y
xyz 1 Y Y
xyz 1 Y NULL
xyz *2* N N
xyz 2 Y NULL
def 1 Y Y
def 1 N NULL
To get the flag2 columns
1.Assign falg2 as flag for rownum=1
2. We have to check the colm1,count of current row with colm1,count of previous row .if the colm1 and cnt are same then we have to assign null...
Below is the query i used to get the flag2 values
SELECT colm1,count,flag
CASE WHEN
LAG(count, 1,null) OVER (PARTITION BY colm1 ORDER BY colm1 DESC NULLS LAST) IS NULL
and LAG(flag, 1, NULL) OVER (PARTITION BY colm1 ORDER BY colm1,cycle DESC NULLS LAST) IS NULL
THEN flag
END AS flag2
FROM table1
but the above query returns the below o/p which is wrong
col1_ count flag flag2
abc 1 Y Y
xyz 1 Y Y
xyz 1 Y NULL
xyz *2* N NULL
xyz 2 Y NULL
def 1 Y Y
def 1 N NULL
Thanks
Edited by: user9370033 on Apr 8, 2010 11:25 PMWell, you haven't quite explained your full requirement in this
1.Assign falg2 as flag for rownum=1
2. We have to check the colm1,count of current row with colm1,count of previous row .if the colm1 and cnt are same then we have to assign null...as you don't say what flag2 should be set to if com1 and cnt are not the same as the previous row.
but how about this as my first guess what you mean...
SQL> with t as (select 'abc' as col1, 1 as cnt, 'Y' as flag from dual union all
2 select 'xyz', 1, 'Y' from dual union all
3 select 'xyz', 1, 'Y' from dual union all
4 select 'xyz', 2, 'N' from dual union all
5 select 'xyz', 2, 'Y' from dual union all
6 select 'def', 1, 'Y' from dual union all
7 select 'def', 1, 'N' from dual)
8 -- END OF TEST DATA
9 select col1, cnt, flag
10 ,case when lag(col1) over (order by col1, cnt) is null then flag
11 when lag(col1) over (order by col1, cnt) = col1 and
12 lag(cnt) over (order by col1, cnt) = cnt then null
13 else flag
14 end as flag2
15 from t
16 /
COL CNT F F
abc 1 Y Y
def 1 Y Y
def 1 N
xyz 1 Y Y
xyz 1 Y
xyz 2 Y Y
xyz 2 N
7 rows selected.
SQL> -
I have a data in this format:
ID
1
2
2
5
5
5
5I need to generate another column next to it in the below format:
ID Rnk
1 1
2 2
2 2
5 3
5 3
5 3
5 3Thank you
KumarHi, Kumar,
DENSE_RANK does that.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/functions045.htm#sthref1315
SELECT id
, DENSE_RANK () OVER (ORDER BY id) AS rnk
FROM table_x
; -
About FIRST_ROW analytic function; can anyone help?
Hi everyone,
Can anyone help me with this simple query?
Let's suppose I have this query (the with clause contains some data):
WITH T AS (
SELECT 'TEST' as COL1, 1 as COL2, 'z' as COL3 FROM dual
UNION ALL
SELECT 'TEST', 2, 'y' FROM dual
UNION ALL
SELECT 'TEST', 2, 'h' FROM dual
SELECT FIRST_VALUE(COL1) OVER (PARTITION BY COL1), COL2, COL3
FROM T;I would like to have only the first row returned. I was thinking that with FIRST_VALUE it will be possible, but it returns 3 records.
So can anyone help me to have only the first record returned?
TEST 1 zThis is just a simple example. In reality I have thousands of records. I need to get only the first record based on the name (TEST in this example). We don't really care about the other columns.
Thanks for your help,user13117585 wrote:
I would like to have only the first row returned. I was thinking that with FIRST_VALUE it will be possible, but it returns 3 records. Analytic functions don't filter rows, they just calculate values from some part of the result set.
Aggregating is the most efficient way of doing this query:
SQL> WITH T AS (
2 SELECT 'TEST' as COL1, 1 as COL2, 'z' as COL3 FROM dual
3 UNION ALL
4 SELECT 'TEST', 2, 'y' FROM dual
5 UNION ALL
6 SELECT 'TEST', 2, 'h' FROM dual
7 )
8 select col1
9 , min(col2) col2
10 , max(col3) keep (dense_rank first order by col2) col3
11 from t
12 group by col1
13 /
COL1 COL2 C
TEST 1 z
1 row selected.Regards,
Rob. -
Help with Oracle Analytic Function scenario
Hi,
I am new to analytic functions and was wondering if someone could help me with the data scenario below. I have a table with the following data
COLUMN A COLUMN B COLUMN C
13368834 34323021 100
13368835 34438258 50
13368834 34438258 50
13368835 34323021 100
The output I want is
COLUMN A COLUMN B COLUMN C
13368834 34323021 100
13368835 34438258 50
A simple DISTINCT won't give me the desired output so i was wondering if there is any way that I can get the result using ANALYTIC FUNCTIONS and DISTINCT ..
Any help will be greatly appreciated.
Thanks.Hi,
Welcome to the forum!
Whenever you have a question, please post your sample data in a form that people can use to re-create the problem and test their solutions.
For example:
CREATE TABLE table_x
( columna NUMBER
, columnb NUMBER
, columnc NUMBER
INSERT INTO table_x (columna, columnb, columnc) VALUES (13368834, 34323021, 100);
INSERT INTO table_x (columna, columnb, columnc) VALUES (13368835, 34438258, 50);
INSERT INTO table_x (columna, columnb, columnc) VALUES (13368834, 34438258, 50);
INSERT INTO table_x (columna, columnb, columnc) VALUES (13368835, 34323021, 100);Do you want something that works in your version or Oracle? Of course you do! So tell us which version that is.
How do you get the results that you want? Explain what each row of output represents. It looks like
the 1st row contains the 1st distinct value from each column (where "first" means descending order for columnc, and ascending order for the others),
the 2nd row contains the 2nd distinct value,
the 3rd row contains the 3rd distinct value, and so on.
If that's what you want, here's one way to get it (in Oracle 9 and up):
WITH got_nums AS
SELECT columna, columnb, columnc
, DENSE_RANK () OVER (ORDER BY columna ) AS a_num
, DENSE_RANK () OVER (ORDER BY columnb ) AS b_num
, DENSE_RANK () OVER (ORDER BY columnc DESC) AS c_num
FROM table_x
SELECT MAX (a.columna) AS columna
, MAX (b.columnb) AS columnb
, MAX (c.columnc) AS columnc
FROM got_nums a
FULL OUTER JOIN got_nums b ON b.b_num = a.a_num
FULL OUTER JOIN got_nums c ON c.c_num = COALESCE (a.a_num, b.b_num)
GROUP BY COALESCE (a.a_num, b.b_num, c.c_num)
ORDER BY COALESCE (a.a_num, b.b_num, c.c_num)
;I've been trying to find a good name for this type of query. The best I've heard so far is "Prix Fixe Query", named after the menus where you get a choice of soups (listed in one column), appetizers (in another column), main dishes (in a 3rd column), and so on. The items on the first row don't necessaily have any relationship to each other.
The solution does not assume that there are the same number of distinct items in each column.
For example, if you add this row to the sample data:
INSERT INTO table_x (columna, columnb, columnc) VALUES (13368835, 34323021, 99);which is a copy of the last row, except that there is a completely new value for columnc, then the output is:
` COLUMNA COLUMNB COLUMNC
13368834 34323021 100
13368835 34438258 99
50starting in Oracle 11, you can also do this with an unpivot-pivot query. -
Does sql analytic function help to determine continuity in occurences
We need to solve this problem in a sql statement.
imagine a table test with two columns
create table test (id char(1), begin number, end number);
and these values
insert into test('a',1, 2);
insert into test('a',2,3);
insert into test('a',3,4);
insert into test('a',7,10);
insert into test('a',10,15);
insert into test('b',5,9);
insert into test('b',9,21);
insert into test('c',1,5);
our goal is to determine continuity in number sequence between begin and end attributes for a same id and determine min and max number from these contuinity chains.
The result may be
a, 1, 4
a, 7, 15
b, 5, 21
c, 1, 5
We test some analytic functions like lag, lead, row_number, min, max, partition by, etc to search a way to identify row set that represent a continuity but we didn't find a way to identify (mark) them so we can use min and max functions to extract extreme values.
Any idea is really welcome !Here is our implementation in a real context for example:
insert into requesterstage(requesterstage_i, requester_i, t_requesterstage_i, datefrom, dateto )
With ListToAdd as
(Select distinct support.requester_i,
support.datefrom,
support.dateto
from support
where support.datefrom < to_date('01.01.2006', 'dd.mm.yyyy')
and support.t_relief_i = t_relief_ipar.fgetflextypologyclassitem_i(t_relief_ipar.fismedicalexpenses)
and not exists
(select null
from requesterstage
where requesterstage.requester_i = support.requester_i
and support.datefrom < nvl(requesterstage.dateto, support.datefrom + 1)
and nvl(support.dateto, requesterstage.datefrom + 1) > requesterstage.datefrom)
ListToAddAnalyzed_1 as
(select requester_i,
datefrom,
dateto,
decode(datefrom,lag(dateto) over (partition by requester_i order by datefrom),0,1) data_set_start
from ListToAdd),
ListToAddAnalyzed_2 as
(select requester_i,
datefrom,
dateto,
data_set_start,
sum(data_set_start) over(order by requester_i, datefrom ) data_set_id
from ListToAddAnalyzed_1)
select requesterstage_iseq.nextval,
requester_i,
t_requesterstage_ipar.fgetflextypologyclassitem_i(t_requesterstage_ipar.fisbefore2006),
datefrom,
decode(sign(nvl(dateto, to_date('01.01.2006', 'dd.mm.yyyy')) -to_date('01.01.2006', 'dd.mm.yyyy')), 0, to_date('01.01.2006', 'dd.mm.yyyy'), -1, dateto, 1, to_date('01.01.2006', 'dd.mm.yyyy'))
from ( select requester_i
, min(datefrom) datefrom
, max(dateto) dateto
From ListToAddAnalyzed_2
group by requester_i, data_set_id
); -
How to achive this using analytical function-- please help
version 10g.
this code works just fine with my requirement. i am tyring to learn analytical functions and implement that in the below query. i tried using row_number ,
but i could nt achive the desired results. please give me some ideas.
SELECT c.tax_idntfctn_nmbr irs_number, c.legal_name irs_name,
f.prvdr_lctn_iid
FROM tax_entity_detail c,
provider_detail e,
provider_location f,
provider_location_detail pld
WHERE c.tax_entity_sid = e.tax_entity_sid
AND e.prvdr_sid = f.prvdr_sid
AND pld.prvdr_lctn_iid = f.prvdr_lctn_iid
AND c.oprtnl_flag = 'A'
AND c.status_cid = 2
AND e.oprtnl_flag = 'A'
AND e.status_cid = 2
AND (c.from_date) =
(SELECT MAX (c1.from_date)
FROM tax_entity_detail c1
WHERE c1.tax_entity_sid = c.tax_entity_sid
AND c1.oprtnl_flag = 'A'
AND c1.status_cid = 2)
AND (e.from_date) =
(SELECT MAX (c1.from_date)
FROM provider_detail c1
WHERE c1.prvdr_sid = e.prvdr_sid
AND c1.oprtnl_flag = 'A'
AND c1.status_cid = 2)
AND pld.oprtnl_flag = 'A'
AND pld.status_cid = 2
AND (pld.from_date) =
(SELECT MAX (a1.from_date)
FROM provider_location_detail a1
WHERE a1.prvdr_lctn_iid = pld.prvdr_lctn_iid
AND a1.oprtnl_flag = 'A'
AND a1.status_cid = 2)thanks
Edited by: new learner on May 24, 2010 7:53 AM
Edited by: new learner on May 24, 2010 10:50 AMMay be like this not tested...
select *
from
SELECT c.tax_idntfctn_nmbr irs_number, c.legal_name irs_name,
f.prvdr_lctn_iid, c.from_date as c_from_date, max(c.from_date) over(partition by c.tax_entity_sid) as max_c_from_date,
e.from_date as e_from_date, max(e.from_date) over(partition by e.prvdr_sid) as max_e_from_date,
pld.from_date as pld_from_date, max(pld.from_date) over(partition by pld.prvdr_lctn_iid) as max_pld_from_date
FROM tax_entity_detail c,
provider_detail e,
provider_location f,
provider_location_detail pld
WHERE c.tax_entity_sid = e.tax_entity_sid
AND e.prvdr_sid = f.prvdr_sid
AND pld.prvdr_lctn_iid = f.prvdr_lctn_iid
AND c.oprtnl_flag = 'A'
AND c.status_cid = 2
AND e.oprtnl_flag = 'A'
AND e.status_cid = 2
AND pld.oprtnl_flag = 'A'
AND pld.status_cid = 2
)X
where c_from_date=max_c_from_date AND e_from_date =max_e_from_date AND
pld_from_date=max_pld_from_date -
Help needed with analytical function
I want to get the employee details of the highest and 2nd highest salaried employee in a particular department. But also the department should have more than 1 employee.
I tried the query and it gave me proper results. But I'm wondering if there is some other alternative than using the subquery.
Here is the table and the result query :
with t as
select 1 emp_id,3 mgr_id,'Rajesh' emp_name,3999 salary,677 bonus,'HR' dpt_nme from dual union
select 2 ,3 ,'Gangz',4500,800,'Finance' from dual union
select 3 ,4 ,'Sid',8000,12000,'IT' from dual union
select 4 ,null,'Ram',5000,677,'HR' from dual union
select 5 ,4,'Shyam',6000,677,'IT' from dual union
select 6 ,4 ,'Ravi',9000,12000,'IT' from dual
select * from
(select emp_id, mgr_id, emp_name, dpt_nme, salary, row_number() over (partition by dpt_nme order by salary desc) rn from t where dpt_nme in
(select dpt_nme from t group by dpt_nme having count(*) > 1)) where rn < 3Hi,
You need a sub-query, but you don't need more than that.
Here's one way to eliminate the extra sub-query:
WITH got_analytics AS
SELECT emp_id, mgr_id, emp_name, dpt_nme, salary
, ROW_NUMBER () OVER ( PARTITION BY dpt_nme
ORDER BY salary DESC
) AS rn
, COUNT (*) OVER ( PARTITION BY dpt_nme
) AS dpt_cnt
FROM t
SELECT emp_id, mgr_id, emp_name, dpt_nme, salary
, rn
FROM got_analytics
WHERE rn < 3
AND dpt_cnt > 1
;Analytic functions are computed after the WHERE clause is applied. Since we need to use the results of the analytic ROW_NUMBER function in a WHERE clause, that means we'll have to compute ROW_NUMBER in a sub-query, and use the results in the WHERE clause of the main query. We can call the analytic COUNT function in the same sub-query, and use its results in the same WHERE clause of the main query.
What results would you want if there's a tie for the 2nd highest salary in some department? For example, if you add this row to your sample data:
select 7 ,3 ,'Sunil',8000,12000,'IT' from dual union? You may want to use RANK instead of ROW_NUMBER. -
Tuning sql with analytic function
Dear friends I've developed one sql :
with REP as
(select /*+ MATERIALIZE */ branch_code,
row_number() over(partition by branch_code, account order by bkg_date desc ) R,
account,
bkg_date,
lcy_closing_bal
from history t
select REP1.branch_code,
REP1.account,
REP1.bkg_date,
REP1.lcy_closing_bal,
NULL AS second,
REP2.bkg_date bkg_date2,
REP2.lcy_closing_bal lcy_closing_bal2,
NULL AS third,
REP3.bkg_date bkg_date3,
REP3.lcy_closing_bal lcy_closing_bal3
from (SELECT * FROM REP WHERE R=1) REP1, (SELECT * FROM REP WHERE R=2) REP2, (SELECT * FROM REP WHERE R=3) REP3
where
(REP1.BRANCH_CODE = REP2.BRANCH_CODE(+) AND REP1.ACCOUNT = REP2.ACCOUNT(+)) AND
(REP1.BRANCH_CODE = REP3.BRANCH_CODE(+) AND REP1.ACCOUNT = REP3.ACCOUNT(+))The point is I want to restrict (tune) REP before it used ,because , as you can see I need maximum three value from REP (where R=1,R=2,R=3) . Which analytic function and with wich options I have to use to receive only 3 values in each branch_code,account groups at the materializing time ?Radrigez wrote:
Dear friends I've developed one sql :
with REP as
from (SELECT * FROM REP WHERE R=1) REP1,
(SELECT * FROM REP WHERE R=2) REP2,
(SELECT * FROM REP WHERE R=3) REP3
where
(REP1.BRANCH_CODE = REP2.BRANCH_CODE(+) AND REP1.ACCOUNT = REP2.ACCOUNT(+)) AND
(REP1.BRANCH_CODE = REP3.BRANCH_CODE(+) AND REP1.ACCOUNT = REP3.ACCOUNT(+))
The first step is to put your subquery (which doesn't need to be materialized) into an inline view and restrict the result set on r in (1,2,3) as suggested by thtsang - you don't need to query the same result set three times.
Then you're looking at a simple pivot operation (assuming the number of rows you want per branch and account is fixed). If you're on 11g search the manuals for PIVOT, on earlier versions you can do this with a decode() or case() operator.
Step 1 (which could go into another factored subquery) would be something like:
select
branch_code, account,
case r = 1 then bkg_date end bkg_date,
case r = 1 then lcy_closing_bal end lcy_closing_bal,
case r = 2 then bkg_date end bkg_date2,
case r = 2 then lcy_closing_bal end lcy_closing_bal2,
case r = 3 then bkg_date end bkg_date3,
case r = 3 then lcy_closing_bal end lcy_closing_bal3
from
repThis gives you the eight necessary columns, but still (up to) three rows per branch/account.
Then you aggregate this (call it rep1) on branch and account.
select
branch_code, account,
max(bkg_date),
max(lcy_closing_bal),
max(bkg_date2),
max(lcy_closing_bal2),
max(bkg_date3),
max(lcy_closing_bal3)
from
rep1
group by
branch_code, account
order by
branch_code, accountRegards
Jonathan Lewis
http://jonathanlewis.wordpress.com
Author: <b><em>Oracle Core</em></b> -
Oracle Analytic function tuning
Hi all,
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.3.0 - Productio
NLSRTL Version 10.2.0.3.0 - Production
I have a query which has analytic function uses large space on temporary tablespace resulting in direct path temp read and direct path temp write wait events taking too much time. Is there any way to tune such query?
Thanks in advance.user9074365 wrote:
Hi all,
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.3.0 - Productio
NLSRTL Version 10.2.0.3.0 - Production
I have a query which has analytic function uses large space on temporary tablespace resulting in direct path temp read and direct path temp write wait events taking too much time. Is there any way to tune such query?
With your version of Oracle, and high-volumes of data going through analytic function, it's likely that this blog note applies. You may need an upgrade or special patch. http://jonathanlewis.wordpress.com/2009/09/07/analytic-agony/
Regards
Jonathan Lewis
Maybe you are looking for
-
How can I delete all delta request and init from InfoCube?
Hi, We are working with an extractor that support deltas, but we are presenting problems with it, some changes in the data are not displayed. For this reason we are thinking change this type of processing and make a full load (with the full updating
-
Mystical total shutdown, error 23 when trying to restore.
Hello. I'm quite desperate at my situation in which I'm at now. The story is as follows: one day at school I took my phone out of my pocket to check for the clock and to my surprise it didn't respond to my actions. Even at that day I listened to musi
-
Still images appear black in final DVD
I am making a 12 minute film on a Dell dimension 2400 using elements 2 (which I have done several times before without problems). Project includes video and still photos. Some of the photos appear black in the timeline and some appear black on the DV
-
Hi, I have a trigger in T-SQL and I need to do the same in an oracle Trigger, with the same table, because I do a migration to Oracle My T-SQL example : -- Traceability -- Variables utiles DECLARE @nID INT, @newValue VARCHAR(50), @myColumn VARCHAR(50
-
Getting the most out of Aperture and FCP
I have been unable to find a thread answering my questions so I thought I'd post my own. I'll start off with a little background info. I do a lot of image processing in Raw with 10MP and 12MP images and would like to run Aperture on my future G5 flaw