'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 |