简体   繁体   中英

Ranking over consecutive dates

I need to get the amount of consecutive unpayments:

with payments as
(
select '1' as ID, '20130331' as DateR, 'Not_paid' as Status from dual
union
select '1' as ID, '20130430' as DateR, 'Paid' as Status from dual
union
select '1' as ID, '20130531' as DateR, 'Not_paid' as Status from dual
union
select '2' as ID, '20130331' as DateR, 'Not_paid' as Status from dual
union
select '2' as ID, '20130430' as DateR, 'Not_paid' as Status from dual
union
select '3' as ID, '20130331' as DateR, 'Paid' as Status from dual
union
select '3' as ID, '20130430' as DateR, 'Paid' as Status from dual
union
select '3' as ID, '20130531' as DateR, 'Paid' as Status from dual
)

select ID, dater, status, dense_rank() over (partition by ID, status order by dater asc) rnk from payments

As you see from this I get the right number of unpayments from id 2: his first unpayment was in March, and the second in April. Id 3 is ok too, because I would exclude him out later on, but for id 1 it says the second unpayment was in May, while I want to make it to be the first because he unpaid in March, but paid again in April so it should start ranking from there. Once he paid his last payment the process starts again.

The idea is to keep it simple without complex queries. I just need to do the same as the dense rank but only when the dates are consecutive

I hope the example is clear enough.

Edit: This is what I get from the current query:

ID    DATER      STATUS   RNK
1   20130331    Not_paid    1
1   20130531    Not_paid    2
1   20130430    Paid        1
2   20130331    Not_paid    1
2   20130430    Not_paid    2
3   20130331    Paid        1
3   20130430    Paid        2
3   20130531    Paid        3

And what I would like to get is this:

 ID   DATER      STATUS   RNK
1   20130331    Not_paid    1
1   20130430    Paid        1
1   20130531    Not_Paid    1
2   20130331    Not_paid    1
2   20130430    Not_paid    2
3   20130331    Paid        1
3   20130430    Paid        2
3   20130531    Paid        3

Such that if I want to get the max(rank) to check how many unpayments a user currently has I get that ID has 1 unpayment, ID 2 two consecutive unpayments, and ID 3 has 0 unpayments. This is because on the forth consecutive unpayment I have to consider the user as churned.

Edit:29/06/2013

Someone gave me a perfect solution in another forum: https://forums.oracle.com/thread/2555552

This isn't a complete answer to your question, but it's a possible solution to get the number of outstanding non-payments for each id. It assigns a value of 1 for a Not_paid status and a -1 for a Paid status. So we can then group the query by ID and sum the value column to get the number of outstanding payments. For sums that are negative, we assign to zero as they have no outstanding payments.

with payments as
(
select '1' as ID, '20130331' as DateR, 'Not_paid' as Status from dual
union
select '1' as ID, '20130430' as DateR, 'Paid' as Status from dual
union
select '1' as ID, '20130531' as DateR, 'Not_paid' as Status from dual
union
select '2' as ID, '20130331' as DateR, 'Not_paid' as Status from dual
union
select '2' as ID, '20130430' as DateR, 'Not_paid' as Status from dual
union
select '3' as ID, '20130331' as DateR, 'Paid' as Status from dual
union
select '3' as ID, '20130430' as DateR, 'Paid' as Status from dual
union
select '3' as ID, '20130531' as DateR, 'Paid' as Status from dual
)
SELECT id,
       DECODE(SIGN(SUM(value)), -1, 0, SUM(value))
  FROM (SELECT id,
               dater,
               status,
               DECODE(status, 'Paid', -1, 1) value
          FROM payments
       )
 GROUP BY id
 ORDER BY id;

Now this query works for the data set in your example, but may not work for bigger data sets. Also it won't work if there aren't at least an equal number of Paid statuses for the Not_paid status. For instance, in your example for ID = 2 , if the account is paid in full in May, there would need to be 2 Paid entries loaded into your table in order for my solution to work. If only 1 Paid entry was loaded, then my solution would still show an outstanding payment required for this ID.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM