Select 每个客户的第一个和第 n 个订单
Select first and nth order for each client
我正在尝试为每个用户显示第一个和第五个 order_id。
Table 看起来像这样:
+----------+-----------+-------------------+
| Order_ID | Client_ID | Datetime |
+----------+-----------+-------------------+
| 1 | 1 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
| 2 | 1 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
| 3 | 2 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
我写了这样的东西:
select
t.client_id,
t.order_id as first_order,
t2.order_id as fifth_order,
t.datetime as first_dt,
t2.datetime as fifth_dt,
from
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) as t
left join
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.order_id) as rn
from "OhMyTable" as o
order by o.order_id
) as t2
on t.client_id = t2.client_id
where t.rn = 1 and t2.rn = 5
但我想看到下了第一个订单但没有第五个订单的客户。应该有NULL,但我不明白如何制作它。 :c
将where t2.rn = 5
条件放入left join
:
select
t.client_id,
t.order_id as first_order,
t2.order_id as fifth_order,
t.datetime as first_dt,
t2.datetime as fifth_dt,
from
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) as t
left join
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.order_id) as rn
from "OhMyTable" as o
order by o.order_id
) as t2
on t.client_id = t2.client_id
and t2.rn = 5
where t.rn = 1 and t2.datetime is null
如果发现条件聚合比两个子查询更简单。您可以使用 having
子句进行过滤:
select client_id,
max(order_id) filter(where rn = 1) first_order,
max(order_id) filter(where rn = 5) fifth_order,
min(datetime) first_dt,
max(datetime) fifth_dt
from (
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) t
where rn in (1, 5)
group by client_id
having count(*) = 2
使用条件聚合:
select o.client_id,
min(datetime) as first_datetime,
max(datetime) as fifth_datime,
max(case when seqnum = 1 then order_id end) as first_orderid,
max(case when seqnum = 5 then order_id end) as fifth_orderid
from (select o.*
row_number() over(partition by o.client_id order by o.datetime) as seqnum
from "OhMyTable" o
) o
where seqnum in (1, 5);
我正在尝试为每个用户显示第一个和第五个 order_id。
Table 看起来像这样:
+----------+-----------+-------------------+
| Order_ID | Client_ID | Datetime |
+----------+-----------+-------------------+
| 1 | 1 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
| 2 | 1 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
| 3 | 2 | YYYYMMDD HH:MM:SS |
+----------+-----------+-------------------+
我写了这样的东西:
select
t.client_id,
t.order_id as first_order,
t2.order_id as fifth_order,
t.datetime as first_dt,
t2.datetime as fifth_dt,
from
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) as t
left join
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.order_id) as rn
from "OhMyTable" as o
order by o.order_id
) as t2
on t.client_id = t2.client_id
where t.rn = 1 and t2.rn = 5
但我想看到下了第一个订单但没有第五个订单的客户。应该有NULL,但我不明白如何制作它。 :c
将where t2.rn = 5
条件放入left join
:
select
t.client_id,
t.order_id as first_order,
t2.order_id as fifth_order,
t.datetime as first_dt,
t2.datetime as fifth_dt,
from
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) as t
left join
(
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.order_id) as rn
from "OhMyTable" as o
order by o.order_id
) as t2
on t.client_id = t2.client_id
and t2.rn = 5
where t.rn = 1 and t2.datetime is null
如果发现条件聚合比两个子查询更简单。您可以使用 having
子句进行过滤:
select client_id,
max(order_id) filter(where rn = 1) first_order,
max(order_id) filter(where rn = 5) fifth_order,
min(datetime) first_dt,
max(datetime) fifth_dt
from (
select o.client_id, o.order_id, o.datetime,
row_number() over(partition by o.client_id order by o.datetime) as rn
from "OhMyTable" as o
) t
where rn in (1, 5)
group by client_id
having count(*) = 2
使用条件聚合:
select o.client_id,
min(datetime) as first_datetime,
max(datetime) as fifth_datime,
max(case when seqnum = 1 then order_id end) as first_orderid,
max(case when seqnum = 5 then order_id end) as fifth_orderid
from (select o.*
row_number() over(partition by o.client_id order by o.datetime) as seqnum
from "OhMyTable" o
) o
where seqnum in (1, 5);