Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle Rank() within (sub)group

I am trying to get the correct rank within a subgroup and am having problems with the outcome. I need to get a rank of each time the group changes based on a timestamp.

For example, using this table:

create table syntrans (
    transid     number,
    launchtime  timestamp,
    status      varchar2(10)
);

insert into syntrans values ( 1, '19-APR-17 07.34.05.824875 PM','FAIL');
insert into syntrans values (  1, '19-APR-17 07.34.06.828753 PM','FAIL');
insert into syntrans values (  1, '19-APR-17 07.34.08.567579 PM','SUCCESS');
insert into syntrans values (  1, '19-APR-17 08.07.31.731745 PM','SUCCESS');
insert into syntrans values (  1, '19-APR-17 08.07.32.735582 PM','SUCCESS');
insert into syntrans values (  2, '19-APR-17 08.17.51.332804 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.17.52.336530 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.19.27.993327 PM','SUCCESS');
insert into syntrans values (  2, '19-APR-17 08.25.54.860077 PM','FAIL');
insert into syntrans values (  2, '19-APR-17 08.25.55.862830 PM','SUCCESS');

What I am current getting is

SELECT transid,
       launchtime,
       status,
       rank() over (partition by status order by launchtime) rnk
  FROM syntrans 
 order by transid, launchtime, status;

   TRANSID LAUNCHTIME                     STATUS            RNK
---------- ------------------------------ ---------- ----------
         1 19-APR-17 07.34.05.824875 PM   FAIL                1
         1 19-APR-17 07.34.06.828753 PM   FAIL                2
         1 19-APR-17 07.34.08.567579 PM   SUCCESS             1
         1 19-APR-17 08.07.31.731745 PM   SUCCESS             2
         1 19-APR-17 08.07.32.735582 PM   SUCCESS             3
         2 19-APR-17 08.17.51.332804 PM   FAIL                3
         2 19-APR-17 08.17.52.336530 PM   FAIL                4
         2 19-APR-17 08.19.27.993327 PM   SUCCESS             4
         2 19-APR-17 08.25.54.860077 PM   FAIL                5
         2 19-APR-17 08.25.55.862830 PM   SUCCESS             5

The output that is needed is like this:

   TRANSID LAUNCHTIME                     STATUS            RNK
---------- ------------------------------ ---------- ----------
         1 19-APR-17 07.34.05.824875 PM   FAIL                1
         1 19-APR-17 07.34.06.828753 PM   FAIL                2
         1 19-APR-17 07.34.08.567579 PM   SUCCESS             1
         1 19-APR-17 08.07.31.731745 PM   SUCCESS             2
         1 19-APR-17 08.07.32.735582 PM   SUCCESS             3
         2 19-APR-17 08.17.51.332804 PM   FAIL                1
         2 19-APR-17 08.17.52.336530 PM   FAIL                2
         2 19-APR-17 08.19.27.993327 PM   SUCCESS             1
         2 19-APR-17 08.25.54.860077 PM   FAIL                1
         2 19-APR-17 08.25.55.862830 PM   SUCCESS             1

...where the "rank" starts over each time the status value changes (ordered by date). I understand that the output I am getting is ranking by the overall status group, but I have not been able to find any combination of functions to get this output needed.

This almost gets it, but not quite:

SELECT transid, launchtime, status, rnk
  FROM (SELECT transid,
              status,
              launchtime,
              RANK() OVER (PARTITION BY transid, status ORDER BY launchtime) rnk
         FROM syntrans )
ORDER BY transid, launchtime;
like image 458
dlivings Avatar asked Nov 08 '22 23:11

dlivings


1 Answers

You can use a difference of row number approach to classify consecutive same status rows as one group. (Run the inner query to see how the groups are assigned.) And then use row_number with these groups.

SELECT transid, launchtime, status
,ROW_NUMBER() over(PARTITION BY transid,grp ORDER BY launchtime) as rnk
FROM (SELECT  transid,
              status,
              launchtime,
              ROW_NUMBER() OVER (PARTITION BY transid ORDER BY launchtime)
              -ROW_NUMBER() OVER (PARTITION BY transid, status ORDER BY launchtime) as grp
         FROM syntrans) t
like image 52
Vamsi Prabhala Avatar answered Nov 15 '22 07:11

Vamsi Prabhala