简体   繁体   中英

Conditional Rank using SQL statements

I have to rank the rows with two conditions.

| CBorderIID  |  CustomerID | CBDate  | orderID    |OrderDate  |
+-------------+-------------+---------+------------+-----------+
|  355253780  |      5314   |1/29/2017| 355253780  | 1/29/2017 |
|  355253780  |      5314   |1/29/2017| 359324061  | 4/5/2017  |
|  355253780  |      5314   |1/29/2017| 368700530  | 5/16/2017 |
|  355253780  |      5314   |1/29/2017| 375164457  | 9/11/2017 |
|  482387847  |      5384   |1/29/2017| 446421606  | 7/27/2018 |
|  482387847  |      5384   |1/29/2017| 449212357  | 8/5/2018  |
|  482387847  |     5384    |1/29/2017| 482387847  | 1/12/2019 |
|  482387847  |      5384   |1/29/2017| 489428993  | 2/23/2019 |

I want to rank the rows with CBorderIID = OrderID as 1 and then when CBorderIID <> OrderID and CBdate < O.orderdate then rank increments

Desired output

| CBorderIID  |  CustomerID | CBDate  | orderID    |OrderDate  | Rank
+-------------+-------------+---------+------------+-----------+------
|  355253780  |      5314   |1/29/2017| 355253780  | 1/29/2017 | 1
|  355253780  |      5314   |1/29/2017| 359324061  | 4/5/2017  | 2
|  355253780  |      5314   |1/29/2017| 368700530  | 5/16/2017 | 3
|  355253780  |      5314   |1/29/2017| 375164457  | 9/11/2017 | 4
|  482387847  |      5384   |1/29/2017| 446421606  | 7/27/2018 | NULL
|  482387847  |      5384   |1/29/2017| 449212357  | 8/5/2018  | NULL
|  482387847  |     5384    |1/29/2017| 482387847  | 1/12/2019 | 1
|  482387847  |      5384   |1/29/2017| 489428993  | 2/23/2019 | 2

I tried row rank with conditions with partition over OrderID but it's not working.

I think this is the logic you want:

select t.*
       (case when CBdate < O.orderdate
             then rank() over (partition by CBorderIID
                               order by ((case when CBorderIID = orderID then 1 else 2 end),
                                         OrderDate
                                        ) as rank
        end)
from t;

Note: If nothing matches CBorderIID = orderID then the first order date will have a rank of 1. If multiple match, then all will have a rank of 1.

These are consistent with how you phrased the question, but there are other possibilities as well.

You can use row_number() with defined groups :

select t.*, 
      (case when grp = 1 and CBdate <= orderdate 
            then row_number() over (partition by CBorderIID, CustomerID, grp order by OrderDate)
       end) as Rank
from (select t.*, 
             sum(case when CBorderIID = orderID then 1 else 0 end) over (partition by CBorderIID, CustomerID order by orderdate) as grp
      from table t
     ) t;

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