[英]MYSQL get First (MIN) and Last (MAX) order records grouped by user
我有一个 mysql 表,它存储所有客户订单如下(简化为问题):
+----------+---------------+------+
| Field | Type | Null |
+----------+---------------+------+
| id (pk) | int(10) | NO |
| cust_id | int(10) | NO |
| total | decimal(10,2) | NO |
| created | datetime) | NO |
+----------+---------------+------+
在一个查询中,我希望获得每个用户的第一个订单以及订单总额和他们最近的订单以及该订单总额
所以我应该有这样的结果:
+----------+------------------+---------------+------------------+---------------+
| cust_id | first_ord_total | first_ord_date| last_ord_total | last_ord_date |
+----------+------------------+---------------+------------------+---------------+
| 123 | 150.48 | 2018-03-01 | 742.25 | 2020-05-19 |
| 456 | 20.99 | 2019-08-01 | 67.22 | 2020-09-17 |
| 789 | 259.99 | 2019-01-01 | 147.15 | 2020-08-31 |
+----------+------------------+---------------+------------------+---------------+
我似乎能够使用 MIN 和 MAX 获取第一个和最后一个订单日期,但我无法将其链接回以提供来自同一订单/记录的订单总数
我知道这是可能的,但我正在努力做到正确
在 MySQL 8+ 上, ROW_NUMBER
在这里派上用场:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY created) rn_first,
ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY created DESC) rn_last
FROM orders
)
SELECT
cust_id,
MAX(CASE WHEN rn_first = 1 THEN total END) AS first_ord_total,
MAX(CASE WHEN rn_first = 1 THEN created END) AS first_ord_date,
MAX(CASE WHEN rn_last = 1 THEN total END) AS last_ord_total,
MAX(CASE WHEN rn_last = 1 THEN created END) AS last_ord_date
FROM cte
GROUP BY
cust_id;
这里的策略是对每个客户使用ROW_NUMBER
来标识 CTE 中的第一个和最后一个交易记录。 然后,我们按客户汇总以查找第一个和最后一个总金额和日期。
如果您的 MySql 版本支持窗口函数,使用 MIN()、MAX() 和 FIRST_VALUE():
select distinct cust_id,
first_value(total) over (partition by cust_id order by created) first_order_total,
min(created) over (partition by cust_id) first_order_date,
first_value(total) over (partition by cust_id order by created desc) last_order_total,
max(created) over (partition by cust_id) last_order_date
from customers
如果没有窗口函数,请使用一个查询来返回每个客户的第一个和最后一个订单日期,并将其连接到使用条件聚合的表中:
select c.cust_id,
max(case when c.created = t.min_created then c.total end) first_order_total,
max(case when c.created = t.min_created then c.created end) first_order_date,
max(case when c.created = t.max_created then c.total end) last_order_total,
max(case when c.created = t.max_created then c.created end) last_order_date
from customers c
inner join (
select cust_id, min(created) min_created, max(created) max_created
from customers
group by cust_id
) t on t.cust_id = c.cust_id and c.created in (t.min_created, t.max_created)
group by c.cust_id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.