Skip to Main Content
  • Questions
  • How to build a query with two counts

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, lalitha.

Asked: June 01, 2000 - 6:31 pm UTC

Last updated: June 04, 2002 - 1:31 pm UTC

Version: version 8.1.5

Viewed 1000+ times

You Asked

Hi Mr Tom,
I have a table with two columns number and date.I need a result set from an sql query which returns three columns ,the first column is the number
the second column is the count of that between a particular date range and
the third column is the count of that number again between another date range.
For e.g if TEST table has two columns with numb and num_date and values
1 01-jan-00
1 02-jan-00
2 01-jan-00
2 06-jan-00

then the result of an sql query should be

numb jan1-jan2 jan3-jan7
1 2 0
2 1 1

Thanks,
Lalitha

and Tom said...

First, I'll show you the 8.1.6 syntax (just to see how much easier this will be....) and then 2 alternative syntaxes for 8.1.5 (the last one works in all releases but is a little hard to read)....

The table I used is:

SQL> create table t ( x int, y date );
Table created.

SQL> insert into t values ( 1,'01-jan-00' );
SQL> insert into t values ( 1,'02-jan-00' );
SQL> insert into t values ( 2,'01-jan-00' );
SQL> insert into t values ( 2,'06-jan-00' );

SQL> insert into t values ( 3,'31-dec-1999' );
SQL> insert into t values ( 3,'01-jan-00' );
SQL> insert into t values ( 3,'02-jan-00' );
SQL> insert into t values ( 3,'03-jan-00' );
SQL> insert into t values ( 3,'04-jan-00' );
SQL> insert into t values ( 3,'05-jan-00' );
SQL> insert into t values ( 3,'06-jan-00' );
SQL> insert into t values ( 3,'07-jan-00' );
SQL> insert into t values ( 3,'08-jan-00' );
SQL> insert into t values ( 3,'09-jan-00' );

I wanted all the boundary values to be present in the test -- dec 31'st is out of range as is 8 and 9 Jan. Jan 2 and 3 are boundary conditions as well...
SQL> select x,
2 sum(case
3 when y between '01-jan-00' and '02-jan-00'
4 then 1
5 else 0
6 end ) jan1_jan2,

7 sum(case
8 when y between '03-jan-00' and '07-jan-00'
9 then 1
10 else 0
11 end ) jan3_jan7
12 from t
13 group by x
14 /

The new case statment in 8.1.6 makes doing this sort of logic pretty easy...

X JAN1_JAN2 JAN3_JAN7
---------- ---------- ----------
1 2 0
2 1 1
3 2 5


In 8.1.5, we can use the trick of "selecting a select" which is almost as easy as the above and would look like this:


SQL> select x,
2 ( select count(*)
3 from t b
4 where b.x = t.x
5 and b.y between '01-jan-00'
6 and '02-jan-00' ) jan1_jan2,
7 ( select count(*)
8 from t b
9 where b.x = t.x
10 and b.y between '03-jan-00'
11 and '07-jan-00' ) jan3_jan7
12 from (select distinct x
13 from t ) t
14 /

X JAN1_JAN2 JAN3_JAN7
---------- ---------- ----------
1 2 0
2 1 1
3 2 5

The above, while it works, will definitely not be as efficient as the CASE statement will be. The above will have to create a set of distinct X's and then for each one of them run 2 subqueries. The case statement will do all of this with 1 scan instead of 1 scan + N * 2 queries. So, how can we do the case statement today in 8.1.5 (and before...)


SQL> select x,
2 sum( decode( sign( y-to_date('03-jan-00') ),
3 -1, decode( sign(y-to_date('01-jan-00')),
4 -1, 0, 1 ), 0 )) jan1_jan2,
5 sum(decode( sign( y-to_date('08-jan-00') ),
6 -1, decode( sign(y-to_date('03-jan-00')),
7 -1, 0, 1 ), 0 )) jan3_jan7
8 from t
9 group by x
10 /

Decode can do it -- its a little obscure but it works. We have to convert:
if y between A and B into:

if y < B
if Y < A
return 0
else
return 1
end if;
else
return 0
end if

Thats what that decode does.


X JAN1_JAN2 JAN3_JAN7
---------- ---------- ----------
1 2 0
2 1 1
3 2 5



Rating

  (2 ratings)

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

Comments

select to produce spread of ranges in columns

Keith Hollins, April 27, 2001 - 10:27 am UTC

I wanted to produce totals and counts of our invoices in ranges of amounts. I was not aware of select from select or case statement.

A search of 'range' and 'decode' in the archives led me quickly to the answer. (I was fed up of working out how to decode)

Sridevi Moparthi, June 04, 2002 - 1:31 pm UTC