'How do I return single orderid having same rank?
I have the following output:
| Orderid | Time | State | Order_rank | 
|---|---|---|---|
| 1 | 10.15 | mfr | 1 | 
| 1 | 10.15 | delivered | 1 | 
| 2 | 12.10 | picked | 1 | 
| 2 | 12.10 | mfr | 1 | 
Here I have ranked the order ids wrt to the latest time and put the condition in where clause "where order_rank = 1", but I want to return a single entry for one orderjobid, i.e. for orderid 1 I want to return the delivered state entry and for orderid 2 I want mfr state entry etc.
This is just a sample data, I have more than 1000s of orderids, how do I return single entry for the same rank?
Solution 1:[1]
Assuming you code looks something like this:
SELECT * FROM (
  SELECT 
     order_id, 
     time, 
     state, 
     RANK() over (partition by order_id order by time) as order_rank
  FROM VALUES
    (1,'10.15','mfr'),
    (1,'10.15','delivered'),
    (2,'12.10','picked'),
    (2,'12.10','mfr')
    v(order_id, time, state)
)
WHERE order_rank = 1;
which gives the output you have.
Not the solution you are looking for, but you can move from the RANK and sub-select and WHERE to use QUALIFY and hide the order_rank line:
SELECT 
   order_id, 
   time, 
   state
FROM VALUES
  (1,'10.15','mfr'),
  (1,'10.15','delivered'),
  (2,'12.10','picked'),
  (2,'12.10','mfr')
  v(order_id, time, state)
QUALIFY RANK() over (partition by order_id order by time) = 1;
But as userMT notes, you want to put a numeric ranking into the selection
like:
     case state
        when 'delivered' then 1
        when 'mfr' then 2
        when 'picked' then 3
        else 4
    end as state_rank,
so if you have it as a separate field, it's easier to read:
 SELECT 
     order_id, 
     time, 
     state, 
     case state
        when 'delivered' then 1
        when 'mfr' then 2
        when 'picked' then 3
        else 4
    end as state_rank
  FROM VALUES
    (1,'10.15','mfr'),
    (1,'10.15','delivered'),
    (2,'12.10','picked'),
    (2,'12.10','mfr')
    v(order_id, time, state)
  QUALIFY RANK() over (partition by order_id order by time,state_rank) = 1;
giving:
| ORDER_ID | TIME | STATE | STATE_RANK | 
|---|---|---|---|
| 1 | 10.15 | delivered | 1 | 
| 2 | 12.10 | mfr | 2 | 
but you can mash the case into the rank also:
  SELECT 
     order_id, 
     time, 
     state
  FROM VALUES
    (1,'10.15','mfr'),
    (1,'10.15','delivered'),
    (2,'12.10','picked'),
    (2,'12.10','mfr')
    v(order_id, time, state)
  QUALIFY RANK() over (partition by order_id order by time, case state when 'delivered' then 1 when 'mfr' then 2 when 'picked' then 3 else 4 end) = 1;
gives:
| ORDER_ID | TIME | STATE | 
|---|---|---|
| 1 | 10.15 | delivered | 
| 2 | 12.10 | mfr | 
Solution 2:[2]
you could try
row_number() over (partition by Orderid order by State) 
and select the first one
Solution 3:[3]
Extend your ranking to include not only the time, but also an expression of state, like.
Order time desc, 
     case state when 'picked' then 1
                When 'mfr' then 2
                When 'delivered' then 3
                ...
     End asc
This way we assign a sort order 1,2,3 to each state.
Edited to make it correct as per comments from @simeon-pilgrim (thanks)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Simeon Pilgrim | 
| Solution 2 | flmelody | 
| Solution 3 | 
