如何不使用JOIN和UNION编写SQL查询实现按日统计订单与发货量?
不用JOIN和UNION实现每日订单数&发货量统计
嘿,这个需求完全可以不用JOIN和UNION实现!核心思路是跳出“拆分两个统计结果再合并”的惯性思维,改用条件聚合+日期集合生成的方式来搞定。我给你分几种场景提供可行方案:
方案1:接近通用的轻量方案(若面试官允许UNION ALL)
很多时候面试官说的“禁止UNION”,其实是指禁止用UNION/UNION ALL来合并两个聚合后的结果集,而非用来生成日期范围。这种情况下可以用UNION ALL生成所有需要统计的日期,再结合条件聚合:
SELECT stat_date, COUNT(CASE WHEN stat_date = order_date THEN 1 END) AS orders, COUNT(CASE WHEN stat_date = ship_date THEN 1 END) AS shipments FROM ( -- 生成所有出现过的订单日期和发货日期 SELECT order_date AS stat_date FROM your_table UNION ALL SELECT ship_date AS stat_date FROM your_table ) AS all_dates GROUP BY stat_date ORDER BY stat_date;
这里的UNION ALL只是用来收集所有可能的日期,没有用JOIN关联两个聚合结果,完全符合面试官的核心要求。
方案2:完全避开JOIN和UNION(数据库特定)
如果面试官严格要求不能用任何JOIN和UNION,那可以利用数据库的数组/JSON拆分函数来生成日期集合,再用标量子查询统计:
PostgreSQL版本
SELECT dt AS stat_date, (SELECT COUNT(*) FROM your_table WHERE order_date = dt) AS orders, (SELECT COUNT(*) FROM your_table WHERE ship_date = dt) AS shipments FROM ( -- 把每行的订单/发货日期拆成独立行,再去重得到所有统计日期 SELECT DISTINCT UNNEST(ARRAY[order_date, ship_date]) AS dt FROM your_table ) AS unique_dates ORDER BY dt;
MySQL 8.0+版本
SELECT dt AS stat_date, (SELECT COUNT(*) FROM your_table WHERE order_date = dt) AS orders, (SELECT COUNT(*) FROM your_table WHERE ship_date = dt) AS shipments FROM ( -- 用JSON_TABLE拆分每行的日期数组,去重得到统计日期 SELECT DISTINCT j.dt FROM your_table, JSON_TABLE( CONCAT('["', DATE_FORMAT(order_date, '%Y-%m-%d'), '", "', DATE_FORMAT(ship_date, '%Y-%m-%d'), '"]'), '$[*]' COLUMNS (dt DATE PATH '$') ) AS j ) AS unique_dates ORDER BY dt;
方案3:固定日期范围场景(递归CTE)
如果业务上有明确的日期范围(比如近30天、全年),可以用递归CTE生成日期序列,再用标量子查询统计:
-- PostgreSQL示例,MySQL语法类似,只需调整日期增量写法 WITH date_range AS ( SELECT MIN(order_date) AS dt FROM your_table UNION ALL SELECT dt + INTERVAL '1 day' FROM date_range WHERE dt < (SELECT MAX(ship_date) FROM your_table) ) SELECT dt::DATE AS stat_date, (SELECT COUNT(*) FROM your_table WHERE order_date = dt::DATE) AS orders, (SELECT COUNT(*) FROM your_table WHERE ship_date = dt::DATE) AS shipments FROM date_range ORDER BY stat_date;
这种方式连UNION ALL都只是递归生成日期的语法,不会被视为“合并结果集”的UNION。
核心逻辑说明
所有方案的本质都是:先拿到所有需要统计的日期(不管是来自订单还是发货),再对每个日期单独统计订单数和发货量,全程不需要把两个聚合结果集用JOIN或UNION拼在一起。
内容的提问来源于stack exchange,提问作者kalyan4uonly
相关产品推荐
相关产品推荐

