You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:52:19