Analytical function count(*) with order by Rows unbounded preceding
Hi
I have query about analytical function count(*) with order by (col) ROWS unbounded preceding.
If i removed order by rows unbouned preceding then it behaves some other way.
Can anybody tell me what is the impact of order by ROWS unbounded preceding with count(*) analytical function?
Please help me and thanks in advance.
Sweety,
CURRENT ROW is the default behaviour of the analytical function if no windowing clause is provided. So if you are giving ROWS UNBOUNDED PRECEDING, It basically means that you want to compute COUNT(*) from the beginning of the window to the current ROW. In other words, the use of ROWS UNBOUNDED PRECEDING is to implicitly indicate the end of the window is the current row
The beginning of the window of a result set will depend on how you have defined your partition by clause in the analytical function.
If you specify ROWS 2 preceding, then it will calculate COUNT(*) from 2 ROWS prior to the current row. It is a physical offset.
Regards,
Message was edited by:
henryswift
Similar Messages
-
Using analytical function - value with highest count
Hi
i have this table below
CREATE TABLE table1
( cust_name VARCHAR2 (10)
, txn_id NUMBER
, txn_date DATE
, country VARCHAR2 (10)
, flag number
, CONSTRAINT key1 UNIQUE (cust_name, txn_id)
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9870,TO_DATE ('15-Jan-2011', 'DD-Mon-YYYY'), 'Iran', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9871,TO_DATE ('16-Jan-2011', 'DD-Mon-YYYY'), 'China', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9872,TO_DATE ('17-Jan-2011', 'DD-Mon-YYYY'), 'China', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9873,TO_DATE ('18-Jan-2011', 'DD-Mon-YYYY'), 'Japan', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9874,TO_DATE ('19-Jan-2011', 'DD-Mon-YYYY'), 'Japan', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9875,TO_DATE ('20-Jan-2011', 'DD-Mon-YYYY'), 'Russia', 1);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9877,TO_DATE ('22-Jan-2011', 'DD-Mon-YYYY'), 'China', 0);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9878,TO_DATE ('26-Jan-2011', 'DD-Mon-YYYY'), 'Korea', 0);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9811,TO_DATE ('17-Jan-2011', 'DD-Mon-YYYY'), 'China', 0);
INSERT INTO table1 (cust_name, txn_id, txn_date,country,flag) VALUES ('Peter', 9854,TO_DATE ('13-Jan-2011', 'DD-Mon-YYYY'), 'Taiwan', 0);
The requirement is to create an additional column in the resultset with country name where the customer has done the maximum number of transactions
(with transaction flag 1). In case we have two or more countries tied with the same count, then we need to select the country (among the tied ones)
where the customer has done the last transaction (with transaction flag 1)
e.g. The count is 2 for both 'China' and 'Japan' for transaction flag 1 ,and the latest transaction is for 'Japan'. So the new column should contain 'Japan'
CUST_NAME TXN_ID TXN_DATE COUNTRY FLAG country_1
Peter 9811 17-JAN-11 China 0 Japan
Peter 9854 13-JAN-11 Taiwan 0 Japan
Peter 9870 15-JAN-11 Iran 1 Japan
Peter 9871 16-JAN-11 China 1 Japan
Peter 9872 17-JAN-11 China 1 Japan
Peter 9873 18-JAN-11 Japan 1 Japan
Peter 9874 19-JAN-11 Japan 1 Japan
Peter 9875 20-JAN-11 Russia 1 Japan
Peter 9877 22-JAN-11 China 0 Japan
Peter 9878 26-JAN-11 Korea 0 Japan
Please let me know how to accomplish this using analytical functions
Thanks
-LearnsequelDoes this work (not spent much time checking it)?
WITH ana AS (
SELECT cust_name, txn_id, txn_date, country, flag,
Sum (flag)
OVER (PARTITION BY cust_name, country) n_trx,
Max (CASE WHEN flag = 1 THEN txn_date END)
OVER (PARTITION BY cust_name, country) l_trx
FROM cnt_trx
SELECT cust_name, txn_id, txn_date, country, flag,
First_Value (country) OVER (PARTITION BY cust_name ORDER BY n_trx DESC, l_trx DESC) top_cnt
FROM ana
CUST_NAME TXN_ID TXN_DATE COUNTRY FLAG TOP_CNT
Fred 9875 20-JAN-11 Russia 1 Russia
Fred 9874 19-JAN-11 Japan 1 Russia
Peter 9873 18-JAN-11 Japan 1 Japan
Peter 9874 19-JAN-11 Japan 1 Japan
Peter 9872 17-JAN-11 China 1 Japan
Peter 9871 16-JAN-11 China 1 Japan
Peter 9811 17-JAN-11 China 0 Japan
Peter 9877 22-JAN-11 China 0 Japan
Peter 9875 20-JAN-11 Russia 1 Japan
Peter 9870 15-JAN-11 Iran 1 Japan
Peter 9878 26-JAN-11 Korea 0 Japan
Peter 9854 13-JAN-11 Taiwan 0 Japan
12 rows selected. -
Analytical Function - COUNT issue
Hello All,
DB Oracle 11g running on Linux x86 64-bit platform ..
I'm curious to know why the below two sets of queries produce different reults.
Q 1
WITH TEMP AS
SELECT 'ONE' VAL, 5 PAR FROM DUAL UNION ALL
SELECT 'ONE' VAL, 7 PAR FROM DUAL UNION ALL
SELECT 'FIVE' VAL, 17 PAR FROM DUAL UNION ALL
SELECT 'FOUR' VAL, 0 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, 78 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, 34 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, -4 PAR FROM DUAL UNION ALL
SELECT 'TWO' VAL, 6 PAR FROM DUAL UNION ALL
SELECT 'TWO' VAL, 12 PAR FROM DUAL
SELECT DISTINCT SUM(PAR) OVER(PARTITION BY VAL), VAL CNT FROM TEMP;
Q2
WITH TEMP AS
SELECT 'ONE' VAL, 5 PAR FROM DUAL UNION ALL
SELECT 'ONE' VAL, 7 PAR FROM DUAL UNION ALL
SELECT 'FIVE' VAL, 17 PAR FROM DUAL UNION ALL
SELECT 'FOUR' VAL, 0 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, 78 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, 34 PAR FROM DUAL UNION ALL
SELECT 'THREE' VAL, -4 PAR FROM DUAL UNION ALL
SELECT 'TWO' VAL, 6 PAR FROM DUAL UNION ALL
SELECT 'TWO' VAL, 12 PAR FROM DUAL
SELECT DISTINCT SUM(PAR) OVER(PARTITION BY VAL ORDER BY PAR) CNT, VAL FROM TEMP;
The only difference between the 2 queries is Q2 has the 'ORDER BY' extra.
For Q2, I was assuming the partitions are ordered by PAR and the SUM is applied over the partition. Obviously, the results prove my assumption is wrong.
So, Q2 is just as good as select * from temp;Hi,
You're right about "ORDER BY par"; it means that the SUM will be from the lowest value of par up to and including the current row.
I think you're ignoring "PARTITION BY val", which means every distinct value of val will be a world unto itself, not affected by any rows with a different value of val. Since val is different on every row, that means the SUM shown will always be the SUM of just that 1 item, so SUM (par) will indeed be the same as par.
Try it without the PARTITION BY clause. -
Problem with Analytical function
hi,
I have two tables and my expected result is given below..
I used the LEAD function to get (start_Date and new_Date) which i have shown in my expected result..my problem is with rel_type and org_id. I am not able to get those values to its corresponding dates..please can any one help...
Table A
ID START_DATE END_DATE REL_TYPE
5001 5/12/2005 7/1/2005 PARTIAL
5001 7/1/2005 7/4/2005 NOTHING
5001 7/4/2005 1/1/5000 FULL
Table B
ID ORG_ID START_DATE END_DATE
5001 102 3/1/2002 3/10/2004
5001 103 3/10/2004 8/1/2005
5001 102 8/1/2005 1/1/5000
Expected Result
start_Date new_date rel_type org_id
3/1/2002 3/10/2004 partial 102
3/10/2004 5/12/2005 partial 103
5/12/2005 7/1/2005 partial 103
7/1/2005 7/4/2005 Nothing 103
7/4/2005 8/1/2005 FULL 103
8/1/2005 1/1/5000 FULL 102
rds,
NagaIs this correct?
<s></s>
with A as
( select 5001 id ,to_date('5/12/2005') start_date, to_date('7/1/2005') end_date,'PERTIAL' rel_type from dual
union all
select 5001,to_date('7/1/2005'),to_date('7/4/2005'), 'NOTHING' from dual
union all
select 5001,to_date('7/4/2005'),to_date('1/1/5000'), 'FULL' from dual
,B as
( select 5001 id ,102 org_id, to_date('3/1/2005') start_date, to_date('3/10/2005') end_date from dual
union all
select 5001, 103, to_date('3/10/2005'),to_date('8/1/2005') from dual
union all
select 5001, 102, to_date('8/1/2005'),to_date('1/1/5000') from dual
/* Data end */
select
start_date
,case when rel_type is null then lead(start_date) over (order by start_date)
else new_date end NEW_DATE
,last_value(rel_type ignore nulls)
over (order by start_date desc rows unbounded preceding) REL_TYPE
,org_id
from (
select
case when B.start_date < A.start_date then A.start_date else B.start_date end START_DATE
,case when B.end_date > A.end_date then A.end_date else B.end_date end NEW_DATE
,A.rel_type
,B.org_id
from A,B
where A.start_date <= B.end_date and B.start_date <= a.end_date
union all
select B.start_date, B.end_date, null, B.org_id
from B
where start_date <= all (select start_date from A)
order by start_date,org_id
START_DATE NEW_DATE REL_TYP ORG_ID
03/01/2005 03/10/2005 PERTIAL 102
03/10/2005 05/12/2005 PERTIAL 103
05/12/2005 07/01/2005 PERTIAL 103
07/01/2005 07/04/2005 NOTHING 103
07/04/2005 08/01/2005 FULL 103
08/01/2005 01/01/5000 FULL 102
6 rows selected.
Oops, there were mistakes on START_DATE NEW_DATE
It has been corrected.
Message was edited by:
ushitaki -
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> -
Return multiple columns from an analytic function with a window
Hello,
Is it possible to obtain multiple columns from an analytic function with a window?
I have a table with 4 columns, an id, a test id, a date, and the result of a test. I'm using an analytic function to obtain, for each row, the current test value, and the maximum test value in the next 2 days like so:
select
id,
test_id,
date,
result,
MAX ( result ) over ( partition BY id, test_id order by date RANGE BETWEEN CURRENT ROW AND INTERVAL '2' DAY FOLLOWING ) AS max_result_next_two_day
from table
This is working fine, but I would like to also obtain the date when the max result occurs. I can see that this would be possible using a self join, but I'd like to know if there is a better way? I cannot use the FIRST_VALUE aggregate function and order by result, because the window function needs to be ordered by the date.
It would be a great help if you could provide any pointers/suggestions.
Thanks,
Dan
http://danieljamesscott.orgAssuming RESULT is a positive integer that has a maximum width of, say 10,
and assuming date has no time-component:
select
id
,test_id
,date
,result
,to_number(substr(max_result_with_date,1,10)) as max_result_next_two_day
,to_date(substr(max_result_with_date,11),'YYYYMMDD') as date_where_max_result_occurs
from (select
id
,test_id
,date
,result
,MAX(lpad(to_char(result),10,'0')||to_char(date,'YYYYMMDD'))
over (partition BY id, test_id
order by date
RANGE BETWEEN CURRENT ROW AND INTERVAL '2' DAY FOLLOWING )
AS max_result_with_date
from table) -
Completion of data series by analytical function
I have the pleasure of learning the benefits of analytical functions and hope to get some help
The case is as follows:
Different projects gets funds from different sources over several years, but not from each source every year.
I want to produce the cumulative sum of funds for each source for each year for each project, but so far I have not been able to do so for years without fund for a particular source.
I have used this syntax:
SUM(fund) OVER(PARTITION BY project, source ORDER BY year ROWS UNBOUNDED PRECEDING)
I have also experimented with different variations of the window clause, but without any luck.
This is the last step in a big job I have been working on for several weeks, so I would be very thankful for any help.If you want to use Analytic functions and if you are on 10.1.3.3 version of BI EE then try using Evaluate, Evaluate_aggr that support native database functions. I have blogged about it here http://oraclebizint.wordpress.com/2007/09/10/oracle-bi-ee-10133-support-for-native-database-functions-and-aggregates/. But in your case all you might want to do is have a column with the following function.
SUM(Measure BY Col1, Col2...)
I have also blogged about it here http://oraclebizint.wordpress.com/2007/10/02/oracle-bi-ee-101332-varying-aggregation-based-on-levels-analytic-functions-equivalence/.
Thanks,
Venkat
http://oraclebizint.wordpress.com -
Hi,
I have a problem using analytic function: when I execute this query
SELECT TSIUPSITE, TSIUPCEAN , TSIUPDATE, sum(TSIUPCA) TSIUPCA, TSIUPCTVA,TSIUPP4N,TSIUPPIEC,
sum(TSIUPQTE) TSIUPQTE,sum(TSIUPQTEP) TSIUPQTEP, TSIUPMDIU,TSIUPMDar,
sum(TSIUPCRIU) TSIUPCRIU,sum(TSIUPCRAR) TSIUPCRAR, trunc(TSIUPDCRE) TSIUPDCRE ,trunc(TSIUPDMAJ) TSIUPDMAJ ,
TSIUPUTIL,TSIUPTRT,TSIUPNERR,TSIUPMESS,
TSIUPTMVT,TSIUPSMAN, TSIUPMOTIF, sum(TSIUPMHT) TSIUPMHT, 0 vtanfisc,
TSIUPDATEVERIF,TSIUPNSEQ,TSIUPCINV ,count(*) over (partition by TSIUPSITE,TSIUPCEAN,TSIUP_TRT ) CONTA_ARTICOLO
FROM TST_FLIISR_VTEREMART
WHERE 1=1 --TSIUP_TRT = 1
AND TSIUPDATE=to_date('27082012','ddmmyyyy')
and TSIUP_NTRX =172
AND TSIUPSITE = 10025
AND TSIUPCEAN = '8012452018825'
GROUP BY TSIUPSITE, TSIUPCEAN , TSIUPDATE, TSIUPCTVA,TSIUPP4N,TSIUPPIEC,
TSIUPMDIU,TSIUPMDar, trunc(TSIUPDCRE),trunc(TSIUPDMAJ),TSIUPUTIL,TSIUPTRT,TSIUPNERR,TSIUPMESS,
TSIUPTMVT,TSIUPSMAN, TSIUPMOTIF, 0,
TSIUPDATEVERIF,TSIUPNSEQ,TSIUPCINV
ORDER BY TSIUPSITE,TSIUPDATE ;
I have the error ORA-00979: not a GROUP BY expression related to TSIUP_TRT field,infact, if I execute this one
SELECT TSIUPSITE, TSIUPCEAN , TSIUPDATE, sum(TSIUPCA) TSIUPCA, TSIUPCTVA,TSIUPP4N,TSIUPPIEC,
sum(TSIUPQTE) TSIUPQTE,sum(TSIUPQTEP) TSIUPQTEP, TSIUPMDIU,TSIUPMDar,
sum(TSIUPCRIU) TSIUPCRIU,sum(TSIUPCRAR) TSIUPCRAR, trunc(TSIUPDCRE) TSIUPDCRE ,trunc(TSIUPDMAJ) TSIUPDMAJ ,
TSIUPUTIL,TSIUPTRT,TSIUPNERR,TSIUPMESS,
TSIUPTMVT,TSIUPSMAN, TSIUPMOTIF, sum(TSIUPMHT) TSIUPMHT, 0 vtanfisc,
TSIUPDATEVERIF,TSIUPNSEQ,TSIUPCINV ,count(*) over (partition by TSIUPSITE,TSIUPCEAN ) CONTA_ARTICOLO
FROM TST_FLIISR_VTEREMART
WHERE 1=1 --TSIUP_TRT = 1
AND TSIUPDATE=to_date('27082012','ddmmyyyy')
and TSIUP_NTRX =172
AND TSIUPSITE = 10025
AND TSIUPCEAN = '8012452018825'
GROUP BY TSIUPSITE, TSIUPCEAN , TSIUPDATE, TSIUPCTVA,TSIUPP4N,TSIUPPIEC,
TSIUPMDIU,TSIUPMDar, trunc(TSIUPDCRE),trunc(TSIUPDMAJ),TSIUPUTIL,TSIUPTRT,TSIUPNERR,TSIUPMESS,
TSIUPTMVT,TSIUPSMAN, TSIUPMOTIF, 0,
TSIUPDATEVERIF,TSIUPNSEQ,TSIUPCINV
ORDER BY TSIUPSITE,TSIUPDATE ;
I have no problem. Now the difference between TSIUPCEAN ( or TSIUPSITE) and TSIUP_TRT is that TSIUP_TRT is not in Group By clause, but, to be honest, I don't know why I have this problem using using an analitic function.
Thanks for helpHi,
I think you are not using analytic function properly.
Analytical functions will execute for each row. Where as Group BY will execute for groups of data.
See below example for you reference.
Example 1:
-- Below query displays number of employees for each department. Since we have used analytical function for each row you are getting the number of employees based on the department id.
SQL> SELECT e.department_id,count(*) OVER (PARTITION BY e.department_id) cnt_analytic
2 FROM employees e
3 WHERE e.department_id IN (10,20,30);
DEPARTMENT_ID CNT_ANALYTIC
10 1
20 2
20 2
30 6
30 6
30 6
30 6
30 6
30 6
9 rows selected.
Example 2:
-- Since I have used GROUP BY clause I'm getting only single row for each department.
SQL> SELECT e.department_id, count(*) cnt_group
2 FROM employees e
3 WHERE e.department_id IN (10,20,30)
4 GROUP BY e.department_id;
DEPARTMENT_ID CNT_GROUP
10 1
20 2
30 6Finally, what I'm trying to explain you is - If you use Analytical function with GROUP BY clause, the query will not give the menaing ful result set.
See below
SQL> SELECT e.department_id,count(*) OVER (PARTITION BY e.department_id) cnt_analytic, count(*) cnt_grp
2 FROM employees e
3 WHERE e.department_id IN (10,20,30)
4 GROUP BY e.department_id;
DEPARTMENT_ID CNT_ANALYTIC CNT_GRP
10 1 1
20 1 2
30 1 6 -
I have a situation where i have partitioned a record set. If in any of the partition on that recordset, the value of one field(field name- status) is '45' i need to order the result of that partition by- 'outdate' desc, 'receiveddate' desc and order the other partition by 'key' desc,' sequence' desc, 'outdate' desc.
So the query looks like -
select row_number() over (partition by key order by sequence) RowNo, key, seq, status, outdate, receivedate from table1 where .........
order by ????
RowNo Key Seq status outdate receiveddate
1 200 0 24 9/13/2009 9/12/2009
2 200 1 23 9/10/2009 9/09/2009
3 200 2 24 9/09/2009 9/08/2009
1 210 0 24 9/13/2009 9/12/2009
2 210 1 * 45 * 9/09/2009 9/08/2009
3 210 2 24 9/10/2009 9/09/2009
So i need to get the query that will order the first set of partition by 'key' desc,' sequence' desc, 'outdate' desc and the Second set of partition (since the status of '45' exist in second partition) by 'outdate' desc, 'receiveddate' desc .
The output of the query should look like
RowNo Key Seq status outdate receiveddate
1 200 0 24 9/13/2009 9/12/2009
2 200 1 23 9/10/2009 9/09/2009
3 200 2 24 9/09/2009 9/08/2009
1 210 0 24 9/13/2009 9/12/2009
2 210 2 24 9/10/2009 9/09/2009
3 210 1 *45 * 9/09/2009 9/08/2009
I am not sure if this is possible using Analytical function.
I would really appreciate if any one can light me on this.
Thanks in advanceHi,
Welcome to the forum!
You can use analytic functions in the ORDER BY clause.
I don't have your tables, so I'll use scott.emp to illustrate.
The following query sorts by deptno first. After that, the sort order for departments that contain at least one Salesman is:
(a) job
(b) ename
Deptno=30 happens to be the only department with a Salesman, so it is the only one sorted as above.
The other departements will be sorted by
(a) sal
(b) job
SELECT deptno
, ename
, job
, sal
FROM scott.emp
ORDER BY deptno
, CASE
WHEN COUNT ( CASE
WHEN job = 'SALESMAN'
THEN 1
END
) OVER (PARTITION BY deptno) > 0
THEN ROW_NUMBER () OVER ( PARTITION BY deptno
ORDER BY job
, ename
ELSE ROW_NUMBER () OVER ( PARTITION BY deptno
ORDER BY sal
, job
END
;Output:
. DEPTNO ENAME JOB SAL
10 MILLER CLERK 1300
10 CLARK MANAGER 2450
10 KING PRESIDENT 5000
20 SMITH CLERK 800
20 ADAMS CLERK 1100
20 JONES MANAGER 2975
20 SCOTT ANALYST 3000
20 FORD ANALYST 3000
30 JAMES CLERK 950
30 BLAKE MANAGER 2850
30 ALLEN SALESMAN 1600
30 MARTIN SALESMAN 1250
30 TURNER SALESMAN 1500
30 WARD SALESMAN 1250
In the small set of sample data you posted, the results you want can be obtained simply using
ORDER BY key
, outdate DESCI assume that's just a coincidence.
If you need help, post some sample data that really requires looking at the status column to get the right results. Post the data in some executable form, such as CREATE TABLE and INSERT statements, olr, as Salim did, a WITH clause. (Perhaps you can just add or change a couple of rows in the sample data Salim already posted.) -
Yet another question on analytical functions
Hi,
A "simple" issue with date overlapping: I need to display a "y" or "n" where a start time/end time overlaps with another row for the same employee.
For this, I used analytical functions to find out which rows were overlapping. This is what I did:
create table test (id number, emp_id number, date_worked date, start_time date, end_time date);
insert into test values (1, 333, to_date('2008-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'));
insert into test values (2, 333, to_date('2008-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'));
insert into test values (3, 444, to_date('2008-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 09:00:00', 'YYYY-MM-DD HH24:MI:SS'));
insert into test values (4, 333, to_date('2008-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 13:00:00', 'YYYY-MM-DD HH24:MI:SS'));
SQL> select * from test;
ID EMP_ID DATE_WORKED START_TIME END_TIME
1 333 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00
2 333 01-01-2008 00:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 --> conflict
3 444 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 09:00:00
4 333 01-01-2008 00:00:00 01-01-2008 11:00:00 01-01-2008 13:00:00 --> conflict Here I see that Employee 333 is scheduled from 10 to 12 am, but it's also scheduled from 11 to 13. This is a conflict.
To find this conflict, I did this (please correct me if this is incorrect):
SQL> select id, emp_id, date_worked, start_time, end_time, next_date
2 from (
3 select lead( start_time, 1 ) over ( partition by emp_id order by start_time ) next_date,
4 start_time, end_time, emp_id, date_worked, id
5 from test
6 )
7 where next_date < end_time;
ID EMP_ID DATE_WORKED START_TIME END_TIME NEXT_DATE
2 333 01-01-2008 00:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 01-01-2008 11:00:00So far, so good. Where I'm stuck is, I need to display the conflicts in this way:
ID EMP_ID DATE_WORKED START_TIME END_TIME OVERLAPPED
1 333 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00
2 333 01-01-2008 00:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 yes
3 444 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 09:00:00
4 333 01-01-2008 00:00:00 01-01-2008 11:00:00 01-01-2008 13:00:00 yes Is there a way I can achieve this?
I tried doing a nested query with a count(*) but no success...I found an issue. Say we insert this row.
insert into test values (5, 333, to_date('2008-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 07:00:00', 'YYYY-MM-DD HH24:MI:SS'),to_date('2008-01-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS'));
SQL> select * from test order by start_time;
ID EMP_ID DATE_WORKED START_TIME END_TIME
5 333 01-01-2008 00:00:00 01-01-2008 07:00:00 01-01-2008 08:00:00
1 333 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00
3 444 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 09:00:00
2 333 01-01-2008 00:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 --> conflict
4 333 01-01-2008 00:00:00 01-01-2008 11:00:00 01-01-2008 13:00:00 --> conflictIf I run the SQL suggested by Nicloei, I get:
SQL> select id,
2 emp_id,
3 date_worked,
4 start_time,
5 end_time,
6 Case When end_time > prev_date Or next_date > End_time Then 'Yes' Else 'No' End over_lap
7 from (
8 select lead( start_time, 1 ) over ( partition by emp_id order by start_time ) next_date,
9 lag( start_time, 1 ) over ( partition by emp_id order by start_time ) prev_date,
10 start_time, end_time, emp_id, date_worked, id
11 from test
12 );
ID EMP_ID DATE_WORKED START_TIME END_TIME OVER_LAP
5 333 01-01-2008 00:00:00 01-01-2008 07:00:00 01-01-2008 08:00:00 No
1 333 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00 Yes
2 333 01-01-2008 00:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 Yes
4 333 01-01-2008 00:00:00 01-01-2008 11:00:00 01-01-2008 13:00:00 Yes
3 444 01-01-2008 00:00:00 01-01-2008 08:00:00 01-01-2008 09:00:00 NoIt's basically saying that there's an overlap between id 1 and id 2 (8-10 and 10-12), which is incorrect. I ran the inner query by itself:
SQL> select lead( start_time, 1 ) over ( partition by emp_id order by start_time ) next_date,
2 lag( start_time, 1 ) over ( partition by emp_id order by start_time ) prev_date,
3 start_time, end_time, emp_id, date_worked, id
4 from test;
NEXT_DATE PREV_DATE START_TIME END_TIME EMP_ID DATE_WORKED ID
01-01-2008 08:00:00 01-01-2008 07:00:00 01-01-2008 08:00:00 333 01-01-2008 00:00:00 5
01-01-2008 10:00:00 01-01-2008 07:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00 333 01-01-2008 00:00:00 1
01-01-2008 11:00:00 01-01-2008 08:00:00 01-01-2008 10:00:00 01-01-2008 12:00:00 333 01-01-2008 00:00:00 2
01-01-2008 10:00:00 01-01-2008 11:00:00 01-01-2008 13:00:00 333 01-01-2008 00:00:00 4
01-01-2008 08:00:00 01-01-2008 09:00:00 444 01-01-2008 00:00:00 3with this data, I can't seem to find a way to conditional test in order to print my overlap column with "yes" or "no" accordingly.
am I missing something? -
Custom window in analytic function
SELECT device_id,
case_id,
value,
fo_value,
nomination,
symbol,
cur_id,
time,
data_type,
COALESCE (
VALUE,
LAST_VALUE (
VALUE IGNORE NULLS
OVER (PARTITION BY device_id, cur_id, nomination
ORDER BY time
ROWS UNBOUNDED PRECEDING)
+ SUM(fo_value)
OVER (PARTITION BY device_id, cur_id, nomination
ORDER BY time
ROWS UNBOUNDED PRECEDING)
AS val
FROM tab
DEVICE_ID CASE_ID VALUE FO_VALUE NOMINATION SYMBOL CUR_ID TIME DATA_TYPE VAL
8744 4901 -23 20 PLN 1 2009-08-25 11:00:00.000000 F -48
8744 4901 -2 20 PLN 1 2009-08-25 07:00:00.000000 F -25
8744 4901 100 -13 20 PLN 1 2009-08-24 23:00:00.000000 I 100
8744 4901 -6 20 PLN 1 2009-08-24 17:00:00.000000 F 45
8744 4901 -5 20 PLN 1 2009-08-24 14:00:00.000000 F 51
8744 4901 -5 20 PLN 1 2009-08-24 11:00:00.000000 F 56VAL column is defined as last VALUE from which there was substracted cummulative sum of FO_VALUE column.
Every record with data_type = 'I' has some number in VALUE column. What I need is to define window in expression that counts sum of FO_VALUE which adds only the values from last NON-NULL VALUE column - currently query substracts all the values in partition.
I need something like window from last NON-NULL in VALUE column row to current row
Desired output should look like this:
DEVICE_ID CASE_ID VALUE FO_VALUE NOMINATION SYMBOL CUR_ID TIME DATA_TYPE VAL
8744 4901 -23 20 PLN 1 2009-08-25 11:00:00.000000 F 62
8744 4901 -2 20 PLN 1 2009-08-25 07:00:00.000000 F 85
8744 4901 100 -13 20 PLN 1 2009-08-24 23:00:00.000000 I 87
8744 4901 -6 20 PLN 1 2009-08-24 17:00:00.000000 F 45
8744 4901 -5 20 PLN 1 2009-08-24 14:00:00.000000 F 51
8744 4901 -5 20 PLN 1 2009-08-24 11:00:00.000000 F 56I'd be very appeciated for any suggestions.Hi,
Sorry, I don't understand the problem.
In particular, I don't see how you get the vals (56, 51, 45) for the earlier times. It looks like you should get NULL for val in the ealiest 3 rows. Can you explain how you get those numbers?
Is it possible for a partition (device_id, cur_id, nomination) to have 2 or more rows where value is not NULL? If so, please post an example of the results you would want.
Rather than adjusting ROWS ... to get the results you want, it might be easier to adjust the PARTITION BY ...
For example, this gets the results you want on and after the row where value is not NULL:
WITH got_grp_num
AS
SELECT device_id, case_id, value, fo_value, nomination, symbol, cur_id, time, data_type,
COUNT (value) OVER ( PARTITION BY device_id, cur_id, nomination
ORDER BY time
) AS grp_num
FROM tab
SELECT device_id, case_id, value, fo_value, nomination, symbol, cur_id, time, data_type,
LAST_VALUE (value IGNORE NULLS) OVER ( PARTITION BY device_id, cur_id, nomination, grp_num
ORDER BY time
+ SUM (fo_value) OVER ( PARTITION BY device_id, cur_id, nomination, grp_num
ORDER BY time
) AS val
FROM got_grp_num
ORDER BY device_id, cur_id, nomination,
time DESC
;As you can see, there is a new column in the PARTITION BY clauses that compute val. The new column is grp_num, which has a new value whenever there is a non-null value.
Edited by: Frank Kulash on Aug 28, 2009 1:27 PM -
[8i] Subquery vs Multiple Analytic Functions
Does anyone have an idea which is better performance-wise?
I have a query that is 3 layers deep already with sub-queries. In the topmost level, I have a choice. I can calculate one analytic function twice, and one analytic function three times, or I can make the topmost level into a subquery, and calculate each analytic function only once.
In case it matters for this problem, this query is running on an 8i database.
A simplified example:
CREATE TABLE my_data
( order_no CHAR(10)
, seq_nbr CHAR(4)
, area_id CHAR(4)
, start_date DATE
, unit_time NUMBER(7,2)
INSERT INTO my_data VALUES ('0000567890','0010','A001',TO_DATE('05/01/2000','mm/dd/yyyy'),0.34);
INSERT INTO my_data VALUES ('0000567890','0020','A001',TO_DATE('05/02/2000','mm/dd/yyyy'),0.78);
INSERT INTO my_data VALUES ('0000567890','0030','A002',TO_DATE('05/03/2000','mm/dd/yyyy'),0.91);
INSERT INTO my_data VALUES ('0000567890','0040','A003',TO_DATE('05/03/2000','mm/dd/yyyy'),0.27);
INSERT INTO my_data VALUES ('0000123456','0010','A001',TO_DATE('04/01/2001','mm/dd/yyyy'),0.39);
INSERT INTO my_data VALUES ('0000123456','0020','A001',TO_DATE('04/02/2001','mm/dd/yyyy'),0.98);
INSERT INTO my_data VALUES ('0000123456','0030','A002',TO_DATE('04/03/2001','mm/dd/yyyy'),0.77);
INSERT INTO my_data VALUES ('0000123456','0040','A003',TO_DATE('04/03/2001','mm/dd/yyyy'),0.28);
INSERT INTO my_data VALUES ('0000123123','0010','A001',TO_DATE('12/01/2001','mm/dd/yyyy'),0.31);
INSERT INTO my_data VALUES ('0000123123','0020','A001',TO_DATE('12/02/2001','mm/dd/yyyy'),0.86);
INSERT INTO my_data VALUES ('0000123123','0030','A002',TO_DATE('12/03/2001','mm/dd/yyyy'),0.82);
INSERT INTO my_data VALUES ('0000123123','0040','A003',TO_DATE('12/03/2001','mm/dd/yyyy'),0.23);
INSERT INTO my_data VALUES ('0000111111','0010','A001',TO_DATE('06/01/2002','mm/dd/yyyy'),0.29);
INSERT INTO my_data VALUES ('0000111111','0020','A001',TO_DATE('06/02/2002','mm/dd/yyyy'),0.84);
INSERT INTO my_data VALUES ('0000111111','0030','A002',TO_DATE('06/03/2002','mm/dd/yyyy'),0.78);
INSERT INTO my_data VALUES ('0000111111','0040','A003',TO_DATE('06/03/2002','mm/dd/yyyy'),0.26);
INSERT INTO my_data VALUES ('0000654321','0010','A001',TO_DATE('05/01/2003','mm/dd/yyyy'),0.28);
INSERT INTO my_data VALUES ('0000654321','0020','A001',TO_DATE('05/02/2003','mm/dd/yyyy'),0.88);
INSERT INTO my_data VALUES ('0000654321','0030','A002',TO_DATE('05/03/2003','mm/dd/yyyy'),0.75);
INSERT INTO my_data VALUES ('0000654321','0040','A003',TO_DATE('05/03/2003','mm/dd/yyyy'),0.25);My choices for the example are:
SELECT area_id
, period_start
, period_end
, AVG(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
STDDEV(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) AS lo_unit_time
, AVG(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) AS avg_unit_time
, AVG(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) +
STDDEV(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) AS hi_unit_time
FROM (
SELECT order_no
, area_id
, ADD_MONTHS(MIN(start_date),-24)+1 AS period_start
, MIN(start_date) AS period_end
, SUM(unit_time) AS tot_area_unit_hrs
FROM my_data
GROUP BY order_no
, area_id
ORDER BY area_id
, period_end
;or
SELECT area_id
, period_start
, period_end
, avg_unit_time - stdev_unit_time AS lo_unit_time
, avg_unit_time
, avg_unit_time + stdev_unit_time AS hi_unit_time
FROM (
SELECT area_id
, period_start
, period_end
, STDDEV(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) AS stdev_unit_time
, AVG(tot_area_unit_hrs)
OVER (
PARTITION BY area_id
ORDER BY period_start
RANGE BETWEEN period_end - period_start PRECEDING
AND CURRENT ROW
) AS avg_unit_time
FROM (
SELECT order_no
, area_id
, ADD_MONTHS(MIN(start_date),-24)+1 AS period_start
, MIN(start_date) AS period_end
, SUM(unit_time) AS tot_area_unit_hrs
FROM my_data
GROUP BY order_no
, area_id
ORDER BY area_id
, period_end
;My gut instinct would be that the 2nd option is faster (with the sub-query), but before I try this on my actual data set which is much larger, I'd like a second opinion. I don't want to accidentally start running a "neverending" query.Sorry for the delay in response here... I was busy deleting 39 GB of trace files, because some silly person (hangs head in shame) accidentally set TRACE_LEVEL_CLIENT=SUPPORT months ago and forgot to turn it off, and didn't notice until her hard drive was full and she couldn't save a file.....
Anyway...
@Dev
For the real query...
option 1 explain plan:
OPERATION OPTIONS OBJECT_NODE OBJECT_OWNER OBJECT_NAME OBJECT_INSTANCE OBJECT_TYPE OPTIMIZER ID PARENT_ID POSITION COST CARDINALITY BYTES
SELECT STATEMENT REMOTE HINT: CHOOSE 0 6076 6076 1 91
SORT ORDER BY 1 0 1 6076 1 91
WINDOW SORT 2 1 1 1 91
SORT GROUP BY 3 2 1 6076 1 91
FILTER 4 3 1
NESTED LOOPS 5 4 1 6071 1 91
TABLE ACCESS FULL DB8I.WORLD ASCHEMA DETAILS 2 6 5 1 6068 1 50
INDEX RANGE SCAN DB8I.WORLD ASCHEMA ORDERS_IX3 UNIQUE ANALYZED 7 5 2 3 141930 5819130
TABLE ACCESS BY INDEX ROWID DB8I.WORLD ASCHEMA DETAILS 3 8 4 2 7 1 44
INDEX RANGE SCAN DB8I.WORLD ASCHEMA DETAILS_IX1 NON-UNIQUE ANALYZED 9 8 1 3 1 option 2 explain plan:
OPERATION OPTIONS OBJECT_NODE OBJECT_OWNER OBJECT_NAME OBJECT_INSTANCE OBJECT_TYPE OPTIMIZER ID PARENT_ID POSITION COST CARDINALITY BYTES
SELECT STATEMENT HINT: CHOOSE 0 2777 2777 96 14208
SORT ORDER BY 1 0 1 2777 96 14208
VIEW LOCALUSER 1 2 1 1 2776 96 14208
WINDOW SORT 3 2 1 2776 96 26400
HASH GROUP BY 4 3 1 2776 96 26400
FILTER 5 4 1
REMOTE DB8I REMOTE 6 5 1 1908 386 59830
REMOTE DB8I DETAILS REMOTE 7 5 2 4 1 129 You should know, in order to get explain plan on these queries, I have to run them via a database link to the 8i database through XE 10g on my local machine, as I don't have access to run explain plan on the remote database itself. I've never seen my local user name appear before in an explain plan run this way, but it did in the one for option #2 (subquery), so I'd guess that wouldn't be the explain plan I'd get if I ran it just in the 8i database. I also find it really odd that the ORDERS table doesn't seem to be referenced in the 2nd explain plan... I do think that's still going to be my best option though, so I'm going to try it and hope it doesn't take too long.
@Frank Kulash
Agreed. That's what I'll try, and I also think that I can't put the analytic function in with the aggregates, without having to do some additional computations in that sub-query, which I think would defeat the purpose of putting them there in the first place. -
COUNT(DISTINCT) WITH ORDER BY in an analytic function
-- I create a table with three fields: Name, Amount, and a Trans_Date.
CREATE TABLE TEST
NAME VARCHAR2(19) NULL,
AMOUNT VARCHAR2(8) NULL,
TRANS_DATE DATE NULL
-- I insert a few rows into my table:
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '110', TO_DATE('06/01/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '20', TO_DATE('06/01/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '110', TO_DATE('06/02/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '21', TO_DATE('06/03/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '68', TO_DATE('06/04/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '110', TO_DATE('06/05/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Anna', '20', TO_DATE('06/06/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Bill', '43', TO_DATE('06/01/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Bill', '77', TO_DATE('06/02/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Bill', '221', TO_DATE('06/03/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Bill', '43', TO_DATE('06/04/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
INSERT INTO TEST ( TEST.NAME, TEST.AMOUNT, TEST.TRANS_DATE ) VALUES ( 'Bill', '73', TO_DATE('06/05/2005 08:00:00 PM', 'MM/DD/YYYY HH12:MI:SS PM') );
commit;
/* I want to retrieve all the distinct count of amount for every row in an analytic function with COUNT(DISTINCT AMOUNT) sorted by name and ordered by trans_date where I get only calculate for the last four trans_date for each row (i.e., for the row "Anna 110 6/5/2005 8:00:00.000 PM," I only want to look at the previous dates from 6/2/2005 to 6/5/2005 and get the distinct count of how many amounts there are different for Anna). Note, I cannot use the DISTINCT keyword in this query because it doesn't work with the ORDER BY */
select NAME, AMOUNT, TRANS_DATE, COUNT(/*DISTINCT*/ AMOUNT) over ( partition by NAME
order by TRANS_DATE range between numtodsinterval(3,'day') preceding and current row ) as COUNT_AMOUNT
from TEST t;
This is the results I get if I just count all the AMOUNT without using distinct:
NAME AMOUNT TRANS_DATE COUNT_AMOUNT
Anna 110 6/1/2005 8:00:00.000 PM 2
Anna 20 6/1/2005 8:00:00.000 PM 2
Anna 110 6/2/2005 8:00:00.000 PM 3
Anna 21 6/3/2005 8:00:00.000 PM 4
Anna 68 6/4/2005 8:00:00.000 PM 5
Anna 110 6/5/2005 8:00:00.000 PM 4
Anna 20 6/6/2005 8:00:00.000 PM 4
Bill 43 6/1/2005 8:00:00.000 PM 1
Bill 77 6/2/2005 8:00:00.000 PM 2
Bill 221 6/3/2005 8:00:00.000 PM 3
Bill 43 6/4/2005 8:00:00.000 PM 4
Bill 73 6/5/2005 8:00:00.000 PM 4
The COUNT_DISTINCT_AMOUNT is the desired output:
NAME AMOUNT TRANS_DATE COUNT_DISTINCT_AMOUNT
Anna 110 6/1/2005 8:00:00.000 PM 1
Anna 20 6/1/2005 8:00:00.000 PM 2
Anna 110 6/2/2005 8:00:00.000 PM 2
Anna 21 6/3/2005 8:00:00.000 PM 3
Anna 68 6/4/2005 8:00:00.000 PM 4
Anna 110 6/5/2005 8:00:00.000 PM 3
Anna 20 6/6/2005 8:00:00.000 PM 4
Bill 43 6/1/2005 8:00:00.000 PM 1
Bill 77 6/2/2005 8:00:00.000 PM 2
Bill 221 6/3/2005 8:00:00.000 PM 3
Bill 43 6/4/2005 8:00:00.000 PM 3
Bill 73 6/5/2005 8:00:00.000 PM 4
Thanks in advance.you can try to write your own udag.
here is a fake example, just to show how it "could" work. I am here using only 1,2,4,8,16,32 as potential values.
create or replace type CountDistinctType as object
bitor_number number,
static function ODCIAggregateInitialize(sctx IN OUT CountDistinctType)
return number,
member function ODCIAggregateIterate(self IN OUT CountDistinctType,
value IN number) return number,
member function ODCIAggregateTerminate(self IN CountDistinctType,
returnValue OUT number, flags IN number) return number,
member function ODCIAggregateMerge(self IN OUT CountDistinctType,
ctx2 IN CountDistinctType) return number
create or replace type body CountDistinctType is
static function ODCIAggregateInitialize(sctx IN OUT CountDistinctType)
return number is
begin
sctx := CountDistinctType('');
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self IN OUT CountDistinctType, value IN number)
return number is
begin
if (self.bitor_number is null) then
self.bitor_number := value;
else
self.bitor_number := self.bitor_number+value-bitand(self.bitor_number,value);
end if;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self IN CountDistinctType, returnValue OUT
number, flags IN number) return number is
begin
returnValue := 0;
for i in 0..log(2,self.bitor_number) loop
if (bitand(power(2,i),self.bitor_number)!=0) then
returnValue := returnValue+1;
end if;
end loop;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self IN OUT CountDistinctType, ctx2 IN
CountDistinctType) return number is
begin
return ODCIConst.Success;
end;
end;
CREATE or REPLACE FUNCTION CountDistinct (n number) RETURN number
PARALLEL_ENABLE AGGREGATE USING CountDistinctType;
drop table t;
create table t as select rownum r, power(2,trunc(dbms_random.value(0,6))) p from all_objects;
SQL> select r,p,countdistinct(p) over (order by r) d from t where rownum<10 order by r;
R P D
1 4 1
2 1 2
3 8 3
4 32 4
5 1 4
6 16 5
7 16 5
8 4 5
9 4 5buy some good book if you want to start at writting your own "distinct" algorythm.
Message was edited by:
Laurent Schneider
a simpler but memory killer algorithm would use a plsql table in an udag and do the count(distinct) over that table to return the value -
Analytic function to count rows based on Special criteria
Hi
I have the following query with analytic function but wrong results on the last column COUNT.
Please help me to achive the required result.Need to change the way how I select the last column.
1)I am getting the output order by b.sequence_no column . This is a must.
2)COUNT Column :
I don't want the total count based on thor column hence there is no point in grouping by that column.
The actual requirement to achieve COUNT is:
2a -If in the next row, if either the THOR and LOC combination changes to a new value, then COUNT=1
(In other words, if it is different from the following row)
2b-If the values of THOR and LOC repeats in the following row, then the count should be the total of all those same value rows until the rows become different.
(In this case 2b-WHERE THE ROWS ARE SAME- also I only want to show these same rows only once. This is shown in the "MY REQUIRED OUTPUT) .
My present query:
select r.name REGION ,
p.name PT,
do.name DELOFF,
ro.name ROUTE,
decode(th.thorfare_name,'OSIUNKNOWN',NULL,th.thorfare_name)
THOR,
l.name LOC ,
b.sequence_no SEQ,
CASE WHEN th.thorfare_name = LAG (th.thorfare_name)
OVER (order by b.sequence_no)
or th.thorfare_name = LEAD (th.thorfare_name)
OVER (order by b.sequence_no)
THEN COUNT(b.sequence_no) OVER (partition by r.name,th.thorfare_name,l.name order BY b.sequence_no
ELSE 1
END COUNT
from t_regions r,t_post_towns p,t_delivery_offices do, t_routes ro, t_counties c,t_head_offices ho,
t_buildings b,t_thoroughfares th,t_localities l
where th.thorfare_id = b.thorfare_id
and nvl(b.invalid,'N')='N'
and b.route_id=ro.route_id(+)
and b.locality_id =l.locality_id(+)
and ro.delivery_office_id=do.delivery_office_id(+)
and do.post_town_id = p.post_town_id(+)
and p.ho_id=ho.ho_id(+)
and ho.county_id = c.county_id(+)
and c.region_id = r.region_id(+)
and r.name='NAAS'
and do.DELIVERY_OFFICE_id= &&DELIVERY_OFFICE_id
and ro.route_id=3405
group by r.name,p.name,do.name,ro.name,th.thorfare_name,l.name,b.sequence_no
ORDER BY ro.name,b.sequence_no;My incorrect output[PART OF DATA]:
>
REGION PT DELOFF ROUTE THOR LOC SEQ COUNT
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 1 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 2 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 PRIMHILL CEL 4 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 5 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 THEGROVE CEL 2 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 7 3
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 8 4
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 9 5
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 10 6
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 11 7
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 12 8
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 15 2
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 19 3
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 24 4
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 29 5
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 34 6
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 39 7
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 42 2
NAAS NAAS MAYNOOTH MAYNOOTHR010 PRIMHILL CEL 43 2
NAAS NAAS MAYNOOTH MAYNOOTHR010 PRIMHILL CEL 44 3
My required output[PART OF DATA]-Please compare with the above.:
>
REGION PT DELOFF ROUTE THOR LOC COUNT
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 PRIMHILL CEL 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 THEGROVE CEL 1
NAAS NAAS MAYNOOTH MAYNOOTHR010 NEWTOWNRD CEL 6
NAAS NAAS MAYNOOTH MAYNOOTHR010 DUBLINRD CEL 7
NAAS NAAS MAYNOOTH MAYNOOTHR010 PRIMHILL CEL 2
NOTE :Count as 1 is correctly coming.
But where there is same rows and I want to take the total count on them, I am not getting.
Pls pls help.
Thanks
Edited by: Krithi on 04-Nov-2010 05:28Nicosa wrote:
Hi,
Can you give us some sample data (create table + inserts orders) to play with ?
Considering your output, I'm not even sure you need analytic count.Yes sure.
I am describing the query again here with 3 tables now to make this understand better.
Given below are the create table statements and insert statements for these 3 tables.
These tables are - BULDINGSV,THORV and LOCV
CREATE TABLE BUILDINGSV
BUILDING_ID NUMBER(10) NOT NULL,
INVALID VARCHAR2(1 BYTE),
ROUTE_ID NUMBER(10),
LOCALITY_ID NUMBER(10),
SEQUENCE_NO NUMBER(4),
THORFARE_ID NUMBER(10) NOT NULL
CREATE TABLE THORV
THORFARE_ID NUMBER(10) NOT NULL,
THORFARE_NAME VARCHAR2(40 BYTE) NOT NULL
CREATE TABLE LOCV
LOCALITY_ID NUMBER(10) NOT NULL,
NAME VARCHAR2(40 BYTE) NOT NULL);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002372, 'N', 3405, 37382613, 5, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002363, 'N', 3405, 37382613, 57, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002362, 'N', 3405, 37382613, 56, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002360, 'N', 3405, 37382613, 52, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002358, 'N', 3405, 37382613, 1, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002240, 'N', 3405, 37382613, 6, 9002284);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002229, 'N', 3405, 37382613, 66, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002228, 'N', 3405, 37382613, 65, 35291872);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002226, 'N', 3405, 37382613, 62, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002222, 'N', 3405, 37382613, 43, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002217, 'N', 3405, 37382613, 125, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002221, 'N', 3405, 37382613, 58, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002214, 'N', 3405, 37382613, 128, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33363182, 'N', 3405, 37382613, 114, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33363185, 'N', 3405, 37382613, 115, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002371, 'N', 3405, 37382613, 2, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003329, 'N', 3405, 37382613, 415, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002359, 'N', 3405, 37382613, 15, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002224, 'N', 3405, 37382613, 61, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003318, 'N', 3405, 37382613, 411, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003326, 'N', 3405, 37382613, 412, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003327, 'N', 3405, 37382613, 413, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003328, 'N', 3405, 37382613, 414, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003330, 'N', 3405, 37382613, 416, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003331, 'N', 3405, 37382613, 417, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27003332, 'N', 3405, 37382613, 410, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27004795, 'N', 3405, 37382613, 514, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(27004807, 'N', 3405, 37382613, 515, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(59002227, 'N', 3405, 37382613, 64, 35291872);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33230805, 'N', 3405, 37382613, 44, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33231027, 'N', 3405, 37382613, 7, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33231058, 'N', 3405, 37382613, 9, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33231078, 'N', 3405, 37382613, 10, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33231087, 'N', 3405, 37382613, 11, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33231093, 'N', 3405, 37382613, 12, 9002375);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(33229890, 'N', 3405, 37382613, 55, 9002364);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561996, 'N', 3405, 34224751, 544, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561997, 'N', 3405, 34224751, 543, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561998, 'N', 3405, 34224751, 555, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562000, 'N', 3405, 34224751, 541, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562001, 'N', 3405, 34224751, 538, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562028, 'N', 3405, 35417256, 525, 0);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562031, 'N', 3405, 35417256, 518, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562032, 'N', 3405, 35417256, 519, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562033, 'N', 3405, 35417256, 523, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561939, 'N', 3405, 34224751, 551, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561940, 'N', 3405, 34224751, 552, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561941, 'N', 3405, 34224751, 553, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561942, 'N', 3405, 35417256, 536, 0);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561943, 'N', 3405, 35417256, 537, 0);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561970, 'N', 3405, 35417256, 522, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561972, 'N', 3405, 35417256, 527, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561974, 'N', 3405, 35417256, 530, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561975, 'N', 3405, 35417256, 531, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561980, 'N', 3405, 34224751, 575, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561981, 'N', 3405, 34224751, 574, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561983, 'N', 3405, 34224751, 571, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561984, 'N', 3405, 34224751, 570, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561985, 'N', 3405, 34224751, 568, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561986, 'N', 3405, 34224751, 567, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561987, 'N', 3405, 34224751, 566, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561989, 'N', 3405, 34224751, 563, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561990, 'N', 3405, 34224751, 562, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561991, 'N', 3405, 34224751, 560, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561992, 'N', 3405, 34224751, 559, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561993, 'N', 3405, 34224751, 558, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561994, 'N', 3405, 34224751, 548, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80561995, 'N', 3405, 34224751, 546, 35417360);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562160, 'N', 3405, 37382613, 139, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562161, 'N', 3405, 37382613, 140, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562162, 'N', 3405, 37382613, 141, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562163, 'N', 3405, 37382613, 142, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562164, 'N', 3405, 37382613, 143, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562165, 'N', 3405, 37382613, 145, 35291878);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562166, 'N', 3405, 37382613, 100, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562167, 'N', 3405, 37382613, 102, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562171, 'N', 3405, 37382613, 107, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562172, 'N', 3405, 37382613, 108, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562174, 'N', 3405, 37382613, 110, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562175, 'N', 3405, 37382613, 111, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562176, 'N', 3405, 37382613, 112, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562177, 'N', 3405, 37382613, 113, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562182, 'N', 3405, 37382613, 123, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562183, 'N', 3405, 37382613, 121, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562184, 'N', 3405, 37382613, 120, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562185, 'N', 3405, 37382613, 118, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562186, 'N', 3405, 37382613, 117, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562187, 'N', 3405, 37382613, 116, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562189, 'N', 3405, 37382613, 95, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562190, 'N', 3405, 37382613, 94, 35291883);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562213, 'N', 3405, 37382613, 89, 35291872);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(80562240, 'N', 3405, 35417256, 516, 35417271);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329559, 'N', 3405, 35329152, 443, 35329551);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329560, 'N', 3405, 35329152, 444, 35329551);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329562, 'N', 3405, 35329152, 446, 35329551);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329109, 'N', 3405, 35329152, 433, 35329181);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329169, 'N', 3405, 35329152, 434, 35329181);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329557, 'N', 3405, 35329152, 441, 35329551);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329558, 'N', 3405, 35329152, 442, 35329551);
Insert into BUILDINGSV
(BUILDING_ID, INVALID, ROUTE_ID, LOCALITY_ID, SEQUENCE_NO, THORFARE_ID)
Values
(35329191, 'N', 3405, 35329152, 436, 35329181);
COMMIT;
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(0, 'OSIUNKNOWN');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(9002284, 'THE GROVE');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(9002364, 'DUBLIN ROAD');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(9002375, 'NEWTOWN ROAD');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35291872, 'HAZELHATCH ROAD');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35291878, 'SIMMONSTOWN PARK');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35291883, 'PRIMROSE HILL');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35329181, 'THE COPSE');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35329213, 'THE COURT');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35329529, 'THE CRESCENT');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35329551, 'THE LAWNS');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35329580, 'THE DRIVE');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35417271, 'TEMPLEMILLS COTTAGES');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(35417360, 'CHELMSFORD');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(36500023, 'THE CLOSE');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(36500101, 'THE GREEN');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37375569, 'THE DOWNS');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37375595, 'THE PARK');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37375754, 'THE AVENUE');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37375781, 'THE VIEW');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37376046, 'THE CRESCENT');
Insert into THORV
(THORFARE_ID, THORFARE_NAME)
Values
(37376048, 'THE GLADE');
COMMIT;
Insert into LOCV
(LOCALITY_ID, NAME)
Values
(34224751, 'SIMMONSTOWN');
Insert into LOCV
(LOCALITY_ID, NAME)
Values
(35417256, 'TEMPLEMILLS');
Insert into LOCV
(LOCALITY_ID, NAME)
Values
(35329152, 'TEMPLE MANOR');
Insert into LOCV
(LOCALITY_ID, NAME)
Values
(37382613, 'CELBRIDGE');
Insert into LOCV
(LOCALITY_ID, NAME)
Values
(37375570, 'SAINT WOLSTAN''S ABBEY');
COMMIT;
------------------------------------------------------------------------------Now the query with wrong result:
select decode(th.thorfare_name,'OSIUNKNOWN',NULL,th.thorfare_name)
THOR,
l.name LOC,
b.sequence_no SEQ,
CASE WHEN th.thorfare_name = LAG (th.thorfare_name)
OVER (order by b.sequence_no)
or th.thorfare_name = LEAD (th.thorfare_name)
OVER (order by b.sequence_no)
THEN COUNT(b.sequence_no) OVER (partition by th.thorfare_name,l.name order BY b.sequence_no
ELSE 1
END COUNT from BUILDINGSV b,THORV th,LOCV l
where th.thorfare_id = b.thorfare_id
and nvl(b.invalid,'N')='N'
and b.route_id=3405
and b.locality_id =l.locality_id(+)
order by b.sequence_no;The query result -WRONG (only first few lines)
THOR LOC SEQ COUNT
DUBLIN ROAD CELBRIDGE 1 1
NEWTOWN ROAD CELBRIDGE 2 1
NEWTOWN ROAD CELBRIDGE 5 2
THE GROVE CELBRIDGE 6 1
NEWTOWN ROAD CELBRIDGE 7 3
NEWTOWN ROAD CELBRIDGE 9 4
NEWTOWN ROAD CELBRIDGE 10 5
NEWTOWN ROAD CELBRIDGE 11 6
NEWTOWN ROAD CELBRIDGE 12 7
DUBLIN ROAD CELBRIDGE 15 1
PRIMROSE HILL CELBRIDGE 43 1
PRIMROSE HILL CELBRIDGE 44 2
DUBLIN ROAD CELBRIDGE 52 3
DUBLIN ROAD CELBRIDGE 55 4
DUBLIN ROAD CELBRIDGE 56 5
DUBLIN ROAD CELBRIDGE 57 6
DUBLIN ROAD CELBRIDGE 58 7
PRIMROSE HILL CELBRIDGE 61 3
PRIMROSE HILL CELBRIDGE 62 4
HAZELHATCH ROAD CELBRIDGE 64 1
HAZELHATCH ROAD CELBRIDGE 65 2The query result -EXPECTED (only first few lines)
THOR LOC COUNT
DUBLIN ROAD CELBRIDGE 1
NEWTOWN ROAD CELBRIDGE 2
THE GROVE CELBRIDGE 1
NEWTOWN ROAD CELBRIDGE 5
DUBLIN ROAD CELBRIDGE 1
PRIMROSE HILL CELBRIDGE 2
DUBLIN ROAD CELBRIDGE 5
PRIMROSE HILL CELBRIDGE 2
HAZELHATCH ROAD CELBRIDGE 2Please note, in the expected result, I only need 1 row but need to show the total count of rows until the names change.
So the issues are
1) the count column values are wrong in my query.
2)I dont want to repeat the same rows(Please see EXPECTED output and compare it against the original)
3)Want the output in exactly same way as in EXPECTED OUTPUT as I dont want to group by thor name(Eg. I dont want the count for all DUBLIN ROAD but I want to examine rows for the next one, if THOR/LOC combination is different in next row then COUNT=1 else COUNT=Count of no. of rows for that thor/loc combination until the combination change -So there are same value multiple rows which i need to show it in 1 row with the total count)
I am explaining below this in more detail!!
I only need 1 row per same THOR/LOC names coming multiple times but I need the count shown against that 1 row(i.e COUNT= how many rows with same thor/loc combination until THOR/LOC combo changes value).
Then repeat the process until all rows are finished..
If there is no multiple row with same THOR/LOC coming in the following row-i.e the following row is a different THOR/LOC combination, then the count for that row is 1.
Hope this is clear.
Is this doable?
Thanks in advance.
Edited by: Krithi on 04-Nov-2010 07:45
Edited by: Krithi on 04-Nov-2010 07:45
Edited by: Krithi on 04-Nov-2010 08:31 -
A function instead of UNBOUNDED PRECEDING (like "Last field with value=0")
Hello,
I have a table with many rows. The attributes of the table are code, month and value.
For each code there are 12 months and 12 values.
No I want to add the gaps between the months...
Is it possible to count the following gaps between the different rows...?
For example:
Original table1:_
code, month, value
1,1,20
1,2,0
1,3,30
1,4,0
1,5,40
1,6,0
1,7,0
1,8,20
1,9,0
1,10,10
1,11,0
1,12,0
5,1,0
5,2,20
5,3,10
description:*
january value = 20
february value = 0 (=>count this gap => new value 1 )
march value = 30
april value = 0 (=>count this gap => new value 1 )
may value = 40
june value = 0
july value = 0 (=>count this two following gaps => new value 2 )
agust value = 20
september value = 0 (=>count this gap => new value 1 )
october value = 10
november value = 0
december value = 0 (=>count this two following gaps => new value 2 )
New target table:_
code, month, value
1,1,20
1,2,*1*
1,3,30
1,4,*1*
1,5,40
1,6,0
1,7,*2*
1,8,20
1,9,*1*
1,10,10
1,11,0
1,12,*2*
5,1,*1*
5,2,20
5,3,10
I tried this code:
select code, month
sum(value) over (
order by month
rows between unbounded preceding and current row
*) as final_value*
from table1 order by month;
This adds all following fields cumulative from beginning to current_row. But I need this adding only for the following gaps... then start with countin by 0.
I need only the following like in the example on top. Maybe is there an other function like decode to count only the following gaps...!?
A function instead of unbounded preceding....like "*Last field with value=0*" or something... ?
Best regards,
TimTimB83 wrote:
I have a table with many rows. The attributes of the table are code, month and value.
For each code there are 12 months and 12 values.
No I want to add the gaps between the months...
Is it possible to count the following gaps between the different rows...?
For example:
Original table1:_
code, month, value
1,1,20
1,2,0
1,3,30
1,4,0
1,5,40
1,6,0
1,7,0
1,8,20
1,9,0
1,10,10
1,11,0
1,12,0
5,1,0
5,2,20
5,3,10
description:*
january value = 20
february value = 0 (=>count this gap => new value 1 )
march value = 30
april value = 0 (=>count this gap => new value 1 )
may value = 40
june value = 0
july value = 0 (=>count this two following gaps => new value 2 )
agust value = 20
september value = 0 (=>count this gap => new value 1 )
october value = 10
november value = 0
december value = 0 (=>count this two following gaps => new value 2 )
New target table:_
code, month, value
1,1,20
1,2,*1*
1,3,30
1,4,*1*
1,5,40
1,6,0
1,7,*2*
1,8,20
1,9,*1*
1,10,10
1,11,0
1,12,*2*
5,1,*1*
5,2,20
5,3,10
...Tim,
you should post this question on the "SQL and PL/SQL" forum since it's a typical SQL question.
There are probably much better ways to accomplish this and the guys over there will tell you, but here are two examples that might get you started:
1. Pre-10g without MODEL clause
with t as (
select 1 as code, 1 as month, 20 as value from dual union all
select 1 as code, 2 as month, 0 as value from dual union all
select 1 as code, 3 as month, 30 as value from dual union all
select 1 as code, 4 as month, 0 as value from dual union all
select 1 as code, 5 as month, 40 as value from dual union all
select 1 as code, 6 as month, 0 as value from dual union all
select 1 as code, 7 as month, 0 as value from dual union all
select 1 as code, 8 as month, 20 as value from dual union all
select 1 as code, 9 as month, 0 as value from dual union all
select 1 as code, 10 as month, 10 as value from dual union all
select 1 as code, 11 as month, 0 as value from dual union all
select 1 as code, 12 as month, 0 as value from dual union all
select 5 as code, 1 as month, 0 as value from dual union all
select 5 as code, 2 as month, 20 as value from dual union all
select 5 as code, 3 as month, 10 as value from dual
r1 as (
select
case
when value = 0
then 1
else 0
end as is_gap
, case
when value != 0
then rownum
else null
end as grp_info
, code
, month
, value
from
t
r2 as (
select
last_value(grp_info ignore nulls) over (partition by code order by month) as grp
, is_gap
, code
, month
, value
from
r1
select
code
, month
, case
when value = 0
and (lead(value) over (partition by code order by month) != 0 or
lead(value) over (partition by code order by month) is null)
then sum(is_gap) over (partition by code, grp)
else value
end as value
from r2;2. 10g and later with MODEL clause
with t as (
select 1 as code, 1 as month, 20 as value from dual union all
select 1 as code, 2 as month, 0 as value from dual union all
select 1 as code, 3 as month, 30 as value from dual union all
select 1 as code, 4 as month, 0 as value from dual union all
select 1 as code, 5 as month, 40 as value from dual union all
select 1 as code, 6 as month, 0 as value from dual union all
select 1 as code, 7 as month, 0 as value from dual union all
select 1 as code, 8 as month, 20 as value from dual union all
select 1 as code, 9 as month, 0 as value from dual union all
select 1 as code, 10 as month, 10 as value from dual union all
select 1 as code, 11 as month, 0 as value from dual union all
select 1 as code, 12 as month, 0 as value from dual union all
select 5 as code, 1 as month, 0 as value from dual union all
select 5 as code, 2 as month, 20 as value from dual union all
select 5 as code, 3 as month, 10 as value from dual
select
code
, month
, value
from
t
model
partition by (code)
dimension by (month)
measures (value, 0 as gap_cnt)
rules (
gap_cnt[any] order by month =
case
when value[cv() - 1] = 0
then gap_cnt[cv() - 1] + 1
else 0
end,
value[any] order by month =
case
when value[cv()] = 0 and presentv(value[cv() + 1], value[cv() + 1], 1) != 0
then presentv(gap_cnt[cv() + 1], gap_cnt[cv() + 1], gap_cnt[cv()] + 1)
else value[cv()]
end
);Regards,
Randolf
Oracle related stuff blog:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle (Open source Oracle GUI for Windows):
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/
Maybe you are looking for
-
How to move ALL my iTunes stuff to a new installation...
Hi there! I have an iTunes library with songs, videos, and PDFs and I want to back it up and move it to my new computer. So I have two partitions on my HDD... I keep all the stuff in a folder on the D:. I then format the C: drive, move the "iTunes" f
-
Switching off summarization of postings from T&E to FI- URGENT
HI All This is a Statutory requirement for Poland 1.In PR05 When the Expense types are Same but appear as 2 different line items ( e.g claimant going from Mumbai too Pune and then from Pune to Nasik there is two entries but the Expense type used is t
-
Photo orientation when sending via email
When I email photos they are displayed in landscape orientation when viewed on the computer but are properly displayed when viewed on the iPhone. Is anyone else having this problem or know how to fix it?
-
Why Reader X AND Reader 9?
The only reason I can imagine for the installation of Reader X to not automatically Uninstall or Overlay the existing Reader 9, would be that Reader 9 has some functionality that Reader X lacks. I cannot find anything on the Adobe site that addresses
-
Hi All, I am facing one issue related to posting of AP document for Intercompany Invoice. The IDOC (Status 51) for AP side is in error because of system is asking for Trading Partner for GL Account because of Substitution rule written. Now My issue i