SQLazy 如何找出每位客戶最早的零訂單記錄
每组内最早出现特定值的记录---AI解法
SQLazy 以四步找出每位客戶最早出現 order_count 為 0 的記錄 row_id,並保留從未出現零訂單的客戶,將其 row_id 設為空值。做法是先整理完整客戶名單,再按客戶分組,從零訂單記錄中取最小 row_id,最後以左連接合併。因 row_id 與 date 同序,取最小 row_id 即代表最早記錄。
2026-11-06 10
版权
版权声明:
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
简介: 本题要求为每位客户找出首个订单数为0的记录row_id,无零单者保留客户并置row_id为NULL。SQLazy通过四步实现:1)提取customer_id;2)去重得完整客户名单;3)按客户分组,在order_count=0的记录中取最小row_id;4)左连接名单与零单结果,确保无零单客户不丢失。逻辑清晰,贴近业务表达。
问题描述
表 records 记录每个客户每天的下单情况,字段为 row_id(行编号)、customer_id(客户编号)、date(日期)、order_count(当天订单数),每个客户的记录都按 date 递增排列,row_id 与 date 同序。现在要针对每个客户,找出他最早出现 order_count 等于 0 的那条记录的 row_id;从来没有下过零单的客户也要出现在结果里,只是 row_id 给空值。
源数据
期望结果
每个客户一行,row_id 是他第一个零单日的记录号,没有零单日则为空:
客户 1 只有一天是零单(2024-01-04,row_id=4),所以结果给 4。
客户 3 有两天是零单(2024-01-01 的 row_id=11、2024-01-04 的 row_id=14),要取更早的那一天,也就是 row_id=11,后一条 14 不能出现在结果里。
客户 2 五天里一天零单都没有,但结果里仍然有他这一行,只是 row_id 是空的。
SQLazy 分步实现
这道题要同时满足两件事:取出零单记录里最早的那一条,又要保住没有零单记录的客户。做法是把这两件事分开:先从原表拿一份完整的客户名单,再从原表按客户分组、只在零单记录里取最小的 row_id,得到 "客户到零单记录" 的对应表,最后把对应表左连接到客户名单上。左连接保证了没配上的客户也留在结果里,配不上的位置自然是空值,正好就是题目要求的 null。
下面逐一解释这些步骤。
第 1 步:取出客户编号这一列
derive customer_id
只留 customer_id 一列,为下一步去重做准备。
第 2 步:得到完整的客户名单
distinct customer_id
按 customer_id 去重,得到每客户一行的完整名单,共 3 行。这份名单用来兜底,保证从未零单的客户也留在结果里。
第 3 步:按客户取最早的零单记录
summarize min row_id condition (order_count=0) as row_id; group customer_id
按 customer_id 分组,聚合算法 min 写在被聚合项 row_id 之前,结果命名为 row_id。条件参数先过滤组内记录,只让 order_count=0 的记录参与聚合,所以算出的是零单记录里最小的 row_id;组内没有零单记录时(如客户 2)结果为空。
取最小 row_id 等于取最早记录,靠的是问题描述里说的 row_id 与 date 同序;数据不同序时要改成按 date 取最小值。
参数次序是聚合、被聚合项、条件、命名,写成先条件后聚合是错的。

第 4 步:把名单和零单记录左连接
join customer_id; with t_zeros; customer_id; take row_id; left
以名单 t_all 为基准表,按 customer_id 关联 t_zeros,拼上它的 row_id。左连接(left)保证名单里的客户一个不丢,配不上的 row_id 为空;用内连接会丢掉客户 2。
编译生成 SQL
确认上述 4 步逻辑后,SQLazy 编译器自动生成原生 SQL(这里是 MySQL 语法):
WITH t_ids AS (
SELECT customer_id
FROM records
),
t_all AS (
SELECT customer_id
FROM t_ids
GROUP BY customer_id
),
t_zeros AS (
SELECT customer_id
, MIN(CASE
WHEN order_count = 0 THEN row_id
ELSE NULL
END) AS row_id
FROM records
GROUP BY customer_id
),
t_result AS (
SELECT t_all.customer_id, t_zeros.row_id
FROM t_all
LEFT JOIN t_zeros ON t_all.customer_id = t_zeros.customer_id
)
SELECT customer_id, row_id
FROM t_result
SQLazy 让你用业务语言描述逻辑,而不是用 SQL 语法写嵌套查询。取最早和保客户这两件事拆成两步各管一件:汇总取零单记录的最小 row_id,左连接保住全部客户。
汇总功能先过滤再聚合:条件参数在聚合前筛一遍,只对零单记录聚合,组内没有零单时自然为空。聚合算法写在被聚合项之前、条件紧随其后,参数次序就是业务说法的次序。
连接方式也是业务语义的直译:保住所有客户写左连接,只留配得上的写内连接。
來源:阿里雲開發者社區 AI · developer.aliyun.com