如何在同一条SQL查询中返回多个分属不同行的聚合结果
方案1:CTE + CROSS JOIN VALUES(全SQL引擎兼容)
WITH filtered_orders AS ( SELECT SalesAmount, OrderId -- 补充其他聚合计算需要用到的字段 FROM Orders o -- 所有过滤条件仅在此处编写一次 WHERE o.OrderDate >= '2023-01-01' AND o.OrderDate < '2024-01-01' AND o.IsValid = 1 ) SELECT CASE metric_name WHEN 'Yearly Sales' THEN SUM(SalesAmount) WHEN 'Yearly Orders' THEN COUNT(DISTINCT OrderId) -- 新增指标只需在此补充对应计算分支 END AS Value, metric_name AS Name, 'Yearly' AS Timeframe FROM filtered_orders CROSS JOIN ( VALUES ('Yearly Sales'), ('Yearly Orders') -- 新增指标只需在此补充对应展示名称 ) AS metrics(metric_name) GROUP BY metric_name
该方案优势:
- 过滤条件仅需维护一份,避免多份重复逻辑出错
- 仅扫描一次订单表,性能远优于多次UNION ALL拼接的写法
- 扩展成本极低,新增指标只需补充两处代码即可
方案2:CTE + UNPIVOT(适配支持逆透视语法的引擎,如SQL Server、Oracle、Spark SQL)
WITH agg_result AS ( SELECT SUM(SalesAmount) AS yearly_sales, COUNT(DISTINCT OrderId) AS yearly_orders -- 所有12个指标先统一计算为单行多列 FROM Orders o -- 过滤条件仅在此处编写一次 WHERE o.OrderDate >= '2023-01-01' AND o.OrderDate < '2024-01-01' AND o.IsValid = 1 ) SELECT Value, Name, 'Yearly' AS Timeframe FROM agg_result UNPIVOT ( Value FOR Name IN ( yearly_sales AS 'Yearly Sales', yearly_orders AS 'Yearly Orders' -- 补充其他指标的列名到展示名称的映射 ) ) AS unpiv_result
该方案适合所有指标为简单聚合的场景,代码结构更简洁直观。
如果使用不支持CTE的低版本SQL引擎,可将CTE逻辑直接改写为对应位置的子查询即可正常运行。
内容的提问来源于stack exchange,提问作者Bryan Tran
相关产品推荐
相关产品推荐

