MySQL查询近6个月消费Top5客户SQL无返回结果问题排查
问题排查思路
从数据层面、SQL逻辑层面逐层排查无结果的原因:
- 数据有效性排查
- 执行
SELECT COUNT(*) FROM orders;确认订单表是否存在数据,若返回0则无任何订单记录,自然查询无结果 - 执行
SELECT COUNT(*) FROM orders o LEFT JOIN customer c ON o.customer_id = c.id WHERE c.id IS NULL;,若返回值等于订单表总条数,说明所有订单的customer_id都是无效值,无法和客户表匹配,内连接后无有效结果 - 执行
SELECT MIN(date), MAX(date) FROM orders;确认订单时间范围,若所有订单时间都距离当前时间超过6个月,符合时间过滤条件后也会无结果
- 执行
- SQL逻辑缺陷排查
- 原SQL未添加近6个月的时间过滤条件,不符合需求要求的时间范围
- 原SQL未添加
GROUP BY分组语句,在开启ONLY_FULL_GROUP_BY等严格SQL模式的数据库中会直接报错,即使不报错也会将所有匹配到的订单合并为单条结果,聚合逻辑完全错误 - 原SQL聚合后别名是
total,和要求输出的sum(price)字段名不一致,若业务侧对返回字段名有强校验也可能被判定为无有效返回
正确SQL实现
根据不同数据库的时间函数差异,给出常用版本的实现,核心逻辑一致:
MySQL 版本
SELECT c.id, c.name, SUM(o.price) AS `sum(price)` FROM customer c INNER JOIN orders o ON c.id = o.customer_id WHERE o.date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) GROUP BY c.id, c.name ORDER BY `sum(price)` DESC LIMIT 5;
PostgreSQL 版本
SELECT c.id, c.name, SUM(o.price) AS "sum(price)" FROM customer c INNER JOIN orders o ON c.id = o.customer_id WHERE o.date >= CURRENT_DATE - INTERVAL '6 months' GROUP BY c.id, c.name ORDER BY "sum(price)" DESC LIMIT 5;
说明:使用内连接会自动过滤近6个月无消费记录的客户,符合"消费总金额最高"的筛选逻辑;如果需要展示无消费客户的0金额记录,可以将
INNER JOIN替换为LEFT JOIN,但这类客户总金额为0不会进入前5名,不影响当前查询结果。
内容的提问来源于stack exchange,提问作者random_programmer
相关产品推荐
相关产品推荐

