如何将SQL分组查询结果从纵向展示改为2009与2010年销售数据横向对比格式?
实现横向展示年份销量的解决方案
当然可以实现这种横向展示的需求!这是典型的**行转列(Pivot)**操作,下面给你两种实用的方案,适配不同的数据库环境:
方案一:通用CASE WHEN实现(适用于所有数据库)
这种方法兼容性最强,不管你用MySQL、PostgreSQL、SQL Server还是其他数据库都能生效。核心思路是用CASE WHEN分别筛选2009和2010年的销量,再通过聚合函数把它们合并到同一行:
SELECT product_sub_category, SUM(CASE WHEN EXTRACT(YEAR FROM order_date) = 2009 THEN sales ELSE 0 END) AS sales_2009, SUM(CASE WHEN EXTRACT(YEAR FROM order_date) = 2010 THEN sales ELSE 0 END) AS sales_2010 FROM data_penjualan WHERE EXTRACT(YEAR FROM order_date) IN (2009, 2010) AND order_status = 'Order Finished' GROUP BY product_sub_category ORDER BY sales_2009 DESC, sales_2010 DESC;
代码说明:
CASE WHEN会根据年份判断是否累加当前行的sales值,非目标年份则返回0,保证每个子品类的两年数据都在同一行- 去掉了原查询中的
years列,因为现在我们把年份作为列名展示了,如果需要保留可以自行调整排序逻辑 - 排序逻辑改成按两年的销量降序,你可以根据需求灵活修改
方案二:使用PIVOT语法(适用于支持该语法的数据库)
如果你的数据库支持PIVOT(比如MySQL 8.0+、SQL Server、Oracle、PostgreSQL 11+),可以用更简洁的语法实现:
以MySQL为例:
SELECT product_sub_category, sales_2009, sales_2010 FROM ( SELECT product_sub_category, sales, CONCAT('sales_', EXTRACT(YEAR FROM order_date)) AS year_col FROM data_penjualan WHERE EXTRACT(YEAR FROM order_date) IN (2009, 2010) AND order_status = 'Order Finished' ) AS pivot_source PIVOT ( SUM(sales) FOR year_col IN ('sales_2009', 'sales_2010') ) AS pivot_table ORDER BY sales_2009 DESC, sales_2010 DESC;
代码说明:
- 子查询先把年份转成
sales_2009、sales_2010这样的列名格式 - PIVOT函数直接对这些列名进行聚合,快速完成行转列
- 不同数据库的PIVOT语法细节略有差异,比如SQL Server不需要给列名加引号,你可以根据自己的数据库调整
这两种方案都能满足你把两年销量横向展示的需求,选一个适合你数据库环境的就行!
内容的提问来源于stack exchange,提问作者Tristianto Raflesia
相关产品推荐
相关产品推荐

