Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Narendra.

Asked: March 19, 2007 - 5:07 am UTC

Last updated: March 19, 2007 - 10:54 am UTC

Version: 8.1.7

Viewed 1000+ times

You Asked

Hi Tom,

I am trying to write a query for following scenario:
We store history of various steps in recruitment process for all candidates.
The requirement is to produce a listing of a report that will display count of
people for each status (having that status) for each month in last one year.
A person's status can change multiple times in a month. The person should be counted under the last status that he/she held within that month. Effectively a person should be counted only once in a month.
Also,

Here is the table structure & sample data:
Connected to Oracle8i Enterprise Edition Release 8.1.7.4.0
Connected as apps


SQL> create table person_status_history (person_id number, status varchar2(15), status_date date );

Table created

SQL> insert into person_status_history values (1, 'INTERVIEWED', to_date('12-JAN-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (1, 'OFFERED', to_date('2-FEB-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (1, 'JOINED', to_date('27-FEB-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (1, 'CONFIRMED', to_date('27-MAR-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (2, 'INTERVIEWED', to_date('22-JAN-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (2, 'OFFERED', to_date('12-FEB-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (3, 'INTERVIEWED', to_date('15-FEB-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (3, 'OFFERED', to_date('17-MAR-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (3, 'JOINED', to_date('27-MAR-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (4, 'INTERVIEWED', to_date('15-DEC-2006','DD-MON-YYYY')) ;

1 row inserted

SQL> insert into person_status_history values (4, 'REJECTED', to_date('5-JAN-2007','DD-MON-YYYY')) ;

1 row inserted

SQL> commit ;

Commit complete

SQL> select to_char(last_days, 'MONTHYYYY'),
2 substr(max_data, 15) status,
3 count(*)
4 from ( select person_id, last_days, max(to_char(status_date, 'YYYYMMDDHH24MISS') || status) max_data
5 from person_status_history psh,
6 ( select add_months(last_day(to_date('01-MAR-2006', 'DD-MON-YYYY')), (rownum - 1)) last_days
7 from all_objects where rownum < 13 ) mth
8 where psh.status_date <= mth.last_days
9 group by person_id, last_days )
10 group by to_char(last_days, 'MONTHYYYY'), substr(max_data, 15) ;


TO_CHAR(LAST_DAYS,'MONTHYYYY') STATUS COUNT(*)
------------------------------- --------------------------------------------- ----------
DECEMBER 2006 INTERVIEWED 1
FEBRUARY 2007 INTERVIEWED 1
FEBRUARY 2007 JOINED 1
FEBRUARY 2007 OFFERED 1
FEBRUARY 2007 REJECTED 1
JANUARY 2007 INTERVIEWED 2
JANUARY 2007 REJECTED 1

7 rows selected


I am not sure whether this is the best approach.
Can you help please ?

and Tom said...

Not sure what the magic with march is there - but given your stated requirements, this is an approach:


ops$tkyte%ORA10GR2> select trunc(status_date,'mm'), status, count(*)
  2    from (
  3  select person_id, status, status_date,
  4         max(status_date) over (partition by person_id, trunc(status_date,'mm')) max_status_date
  5    from person_status_history
  6         )
  7   where status_date = max_status_date
  8   group by trunc(status_date,'mm'), status
  9   order by 1, 2
 10  /

TRUNC(STA STATUS            COUNT(*)
--------- --------------- ----------
01-DEC-06 INTERVIEWED              1
01-JAN-07 INTERVIEWED              2
01-JAN-07 REJECTED                 1
01-FEB-07 INTERVIEWED              1
01-FEB-07 JOINED                   1
01-FEB-07 OFFERED                  1
01-MAR-07 CONFIRMED                1
01-MAR-07 JOINED                   1

8 rows selected.

Rating

  (1 rating)

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

Comments

Got it...

Narendra Prabhudesai, March 19, 2007 - 11:59 am UTC

Tom,

Thanks a lot for the solution.
I also figured that the approach that I was using to limit the data for "last one year" was not quite adequate. I am changing it to much simpler way by accepting the date-range (From Date & To Date) from the user.

More to Explore

Analytics

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