Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: June 06, 2006 - 5:25 pm UTC

Last updated: June 07, 2006 - 7:47 am UTC

Version: 9.2.0.6

Viewed 1000+ times

You Asked

I have a following table in which we insert records through a batch process.

create table emp
(batch_id number(10),
empno number(10),
ename varchar2(35),
deptno number(10));


insert into emp
values (1,10,'XXX',10);

insert into emp
values (1,11,'YYY',10);

insert into emp
values (1,12,'ZZZ',20);

insert into emp
values (2,20,'XXX',10);

insert into emp
values (2,21,'YYY',20);

insert into emp
values (2,22,'ZZZ',20);

After inserting second batch, I want to find out percentage difference in number of employees for each department.

select distinct batch_id,deptno,ct from (
select batch_id,deptno,
count(*) over (partition by batch_id,deptno) as ct
from emp)

BATCH_ID DEPTNO CT

1 10 2
1 20 1
2 10 1
2 20 2

I want another column for batch_id=2 that will tell me percentage change for each deptno from batch_id 1 to 2. Is this possible using analytics?

Thanks
HS

and Tom said...

well, you would never use analytics in the fashion you did. IF you can use an aggregate, by all means USE IT

ops$tkyte@ORA10GR2> select batch_id, deptno, count(*)
2 from emp
3 group by batch_id, deptno
4 order by 1, 2;

BATCH_ID DEPTNO COUNT(*)
---------- ---------- ----------
1 10 2
1 20 1
2 10 1
2 20 2

No need for analytics to do batch over batch comparisons either:


ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> select deptno, b1, b2, case when b1 <> 0 then round( b2/b1*100, 2 ) end pct
2 from (
3 select deptno,
4 count(decode( batch_id, 1, 1 )) b1,
5 count(decode( batch_id, 2, 1 )) b2
6 from emp
7 group by deptno
8 )
9 order by deptno
10 /

DEPTNO B1 B2 PCT
---------- ---------- ---------- ----------
10 2 1 50
20 1 2 200


Always good to make test cases more interesting:

ops$tkyte@ORA10GR2> insert into emp
2 values (2,22,'ZZZ',30);

1 row created.

ops$tkyte@ORA10GR2> insert into emp
2 values (1,22,'ZZZ',40);

1 row created.

ops$tkyte@ORA10GR2> select deptno, b1, b2, case when b1 <> 0 then round( b2/b1*100, 2 ) end pct
2 from (
3 select deptno,
4 count(decode( batch_id, 1, 1 )) b1,
5 count(decode( batch_id, 2, 1 )) b2
6 from emp
7 group by deptno
8 )
9 order by deptno
10 /

DEPTNO B1 B2 PCT
---------- ---------- ---------- ----------
10 2 1 50
20 1 2 200
30 0 1
40 1 0 0


Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

more than 2 batches?

Gabe, June 07, 2006 - 9:32 am UTC

insert into emp select 3, empno, ename, deptno from emp;


gabe@XE> select batch_id,deptno,cnt
2 ,round((cnt/lag(cnt) over (partition by deptno order by batch_id)-1)*100,2) pct_cnt_change
3 from ( select batch_id,deptno, count(*) cnt
4 from emp
5 group by batch_id,deptno
6 )
7 order by batch_id,deptno
8 ;

BATCH_ID DEPTNO CNT PCT_CNT_CHANGE
---------- ---------- ---------- --------------
1 10 2
1 20 1
1 40 1
2 10 1 -50
2 20 2 100
2 30 1
3 10 3 200
3 20 3 50
3 30 1 0
3 40 1 0

10 rows selected.

Elapsed: 00:00:00.01

Not sure if the last line should be (3,40,1,null) rather than (3,40,1,0). As in, "precisely the previous batch" or just "the previous batch which loaded the given deptno"?


Excellent

HS, June 07, 2006 - 9:51 am UTC

As soon as I saw the link to submit answer, I came up with the crude and dirty test case.

Your answer gives me exactly what I wanted. The twist that you gave with insert of deptno 30 and 40 allowed me to clarify the requirement with business.

GABE: There will be only two batches of data in the table. So its "precisely the previous batch".

thanks

More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.