如何合并行数不同的SQL查询结果,实现多维度月度统计
解决方案:合并SQL查询并处理缺失月份数据
问题说明
需要合并两个SQL查询结果,按月份展示以下指标:
- 月份
- 唯一购买客户数(CustomerID)
- 发票数(InvoiceID)
- 商品数(ProductId)
- 总营收(Income)
- 商品A的总营收
原问题在于商品A的月度数据行数少于主统计查询,直接合并会丢失部分月份数据。
示例数据表
| CustomerID | InvoiceID | ProductId | Date | Income |
|---|---|---|---|---|
| 1 | 101 | A | 1/11/2016 | 600 |
| 2 | 103 | B | 12/10/2015 | 300 |
方法1:条件聚合(推荐,性能更优)
无需拆分两个查询,直接在一次表扫描中计算所有指标,自动处理缺失月份(无商品A营收的月份返回0):
SELECT MONTH(date) AS month, COUNT(DISTINCT customerId) AS numOfCustomers, SUM(income) AS sumOfIncome, COUNT(invoiceId) AS numOfInvoice, COUNT(productId) AS numOfProduct, -- 仅统计商品A的营收,无数据时返回0 SUM(CASE WHEN productId = 'A' THEN income ELSE 0 END) AS sumOfIncomeA FROM x WHERE YEAR(date) = 2016 GROUP BY MONTH(date) ORDER BY month;
方法2:LEFT JOIN 合并原有查询
如果必须保留原有两个查询的结构,用LEFT JOIN以主统计的月份为基准,并用COALESCE将缺失的商品A营收转为0:
WITH main_stats AS ( -- 主统计查询 SELECT MONTH(date) AS month, COUNT(DISTINCT customerId) AS numOfCustomers, SUM(income) AS sumOfIncome, COUNT(invoiceId) AS numOfInvoice, COUNT(productId) AS numOfProduct FROM x WHERE YEAR(date) = 2016 GROUP BY MONTH(date) ), product_a_stats AS ( -- 商品A营收查询 SELECT MONTH(date) AS month, SUM(income) AS sumOfIncomeA FROM x WHERE productId = 'A' AND YEAR(date) = 2016 GROUP BY MONTH(date) ) -- 左连接保留所有主统计的月份 SELECT m.month, m.numOfCustomers, m.sumOfIncome, m.numOfInvoice, m.numOfProduct, COALESCE(p.sumOfIncomeA, 0) AS sumOfIncomeA FROM main_stats m LEFT JOIN product_a_stats p ON m.month = p.month ORDER BY m.month;
关键说明
- 方法1的条件聚合只需要扫描一次数据表,性能远优于两次查询+JOIN的方式。
COALESCE函数用于将NULL值(无商品A营收的月份)替换为0,保证数据格式统一。
内容的提问来源于stack exchange,提问作者Mimi
相关产品推荐
相关产品推荐

