基于订单数与用户信息的客户奖金资格分类查询需求
解决方案
表结构与数据
Orders表
| Customer_ID | ORDER_ID | STATUS |
|---|---|---|
| A | 11 | completed |
| A | 12 | completed |
| B | 13 | completed |
| B | 14 | completed |
| B | 15 | completed |
| C | 16 | completed |
| B | 17 | cancelled |
| A | 18 | cancelled |
Customers表
| Customer_ID | Customer_status | join_date |
|---|---|---|
| A | 15 | 2022-02-09 |
| b | 15 | 2022-02-10 |
| c | 10 | 2022-02-10 |
原SQL问题分析
你写的SQL存在几个关键问题:
- 关联后过滤丢失客户:LEFT JOIN后在WHERE子句中过滤
T2.Customer_status=15等条件,会将LEFT JOIN转为INNER JOIN,无法保留所有客户。 - 状态值匹配错误:Orders表的STATUS是字符串类型(如
completed),你用数字6判断,完全不匹配。 - 订单统计范围错误:直接
count(T1.ORDER_ID)会统计所有订单(包括取消的),但需求只统计已完成的订单。 - 缺少分类逻辑:没有实现奖金合格/不合格的判断逻辑,仅做了订单数统计。
正确SQL实现
SELECT c.Customer_ID, CASE WHEN c.Customer_status = 15 AND c.join_date = '2022-02-10' AND COALESCE(COUNT(CASE WHEN o.STATUS = 'completed' THEN o.ORDER_ID END), 0) > 1 THEN '奖金合格' ELSE '奖金不合格' END AS bonus_status FROM Customers c LEFT JOIN Orders o ON UPPER(c.Customer_ID) = o.Customer_ID GROUP BY c.Customer_ID, c.Customer_status, c.join_date ORDER BY c.Customer_ID;
关键说明
- 以客户表为主关联订单:用Customers做主表做LEFT JOIN,确保所有客户都能出现在结果中,不会遗漏。
- 统一ID大小写:原表中Customers的ID有小写(b、c),Orders的ID是大写(B、C),用
UPPER()统一后才能正确关联。 - 精准统计已完成订单:通过
CASE WHEN o.STATUS = 'completed' THEN o.ORDER_ID END筛选已完成订单,再用COUNT统计数量;COALESCE处理无订单的极端情况,确保统计值不为NULL。 - CASE语句实现分类:严格按照需求的三个条件判断,满足则标记为「奖金合格」,其余全部标记为「奖金不合格」。
执行结果
| Customer_ID | bonus_status |
|---|---|
| A | 奖金不合格 |
| b | 奖金合格 |
| c | 奖金不合格 |
内容的提问来源于stack exchange,提问作者Nancy Elhossiny
相关产品推荐
相关产品推荐

