Here is a task I need to get three elements based on the given conditions: three elements: user_id, order_time, ordered_subject
- each unique user_id
- earliest order_time
- ordered_subjects' order should be app-> acc ->ayy
- if there are several order_time are the same, you should take only one subject followed by the 3rd requirement
original table: user_order
user_id | order_time | ordered_subject |
---|---|---|
1 | 2001-02-09 | app |
2 | 2001-02-09 | app |
3 | 2001-02-10 | ayy |
1 | 2001-02-09 | acc |
1 | 2001-02-10 | app |
4 | 2001-02-08 | ayy |
5 | 2001-02-09 | acc |
5 | 2001-02-09 | ayy |
expected table:
user_id | order_time | ordered_subject |
---|---|---|
1 | 2001-02-09 | app |
2 | 2001-02-09 | app |
3 | 2001-02-10 | ayy |
4 | 2001-02-08 | ayy |
5 | 2001-02-09 | acc |
I come up with the idea of case when and row_number() over, but it doesn't work
the code I tried:
select
a.uid,
a.subject,
b.min_time,
(case when "app" then 1
when "acc" then 2
when "ayy" then 3
else 4 end) as rn,
row_number() over(partition by
concat(uid,order_id)
order by
rn)
from (
select uid, min(order_time) as min_time
from user_order
group by
uid
) as b
-- join
user_order as a
-- on
where
a.uid = b.uid
and
b.min_time = a.order_time
How should I fix this? Thank you:)
CodePudding user response:
You want one result row per user. Per user you want the earliest order and if there is more than one order on the earliest date you prefer the order subject app over acc and acc over ayy.
You want to use ROW_NUMBER
, so partition by user ID and order by date and the order subject in the desired order.
select user_id, order_time, ordered_subject
from
(
select
user_id, order_time, ordered_subject,
row_number() over
(partition by user_id
order by order_time,
case ordered_subject
when 'app' then 1
when 'acc' then 2
when 'ayy' then 3
else 4
end) as rn
from mytable
) numbered
where rn = 1
order by user_id;