典型回答

行转列

所谓行转列,就是假设有如下数据表 sales

idyearproductsales
12020A100
22020B200
32021A150
42021B300

要将 product 列的不同值(A 和 B)变为列标题,year 作为行标题,生成如下结果:

yearAB
2020100200
2021150300

这里,可以使用CASE WHEN THEN 用来根据条件为每个 product 创建一列,并通过 SUM 聚合同一年份的销售数据,达到行转列的效果。

1
2
3
4
5
6
SELECT
    year,
    SUM(CASE WHEN product = 'A' THEN sales ELSE 0 END) AS A,
    SUM(CASE WHEN product = 'B' THEN sales ELSE 0 END) AS B
FROM sales
GROUP BY year;

简答解释下:

  • **SUM(CASE WHEN product = 'A' THEN sales ELSE 0 END) AS A**
  • 使用 CASE WHEN 判断 product 是否为 A
    • 如果是 A,则返回该行的 sales 值。
    • 如果不是 A,则返回 0
  • 然后,SUM 函数将每个 year 内所有 product = 'A'sales 值加总,最终得到该 year 对应的 A 产品总销售额。

还可以使用IF实现类似CASE WHEN的功能:

1
2
3
4
5
6
SELECT
    year,
    SUM(IF(product = 'A', sales, 0)) AS A,
    SUM(IF(product = 'B', sales, 0)) AS B
FROM sales
GROUP BY year;

列转行

所谓列转行,假设有如下数据表 sales_data :

yearAB
2020100200
2021150300

转成如下格式结构:

yearproductsales
2020A100
2020B200
2021A150
2021B300

通常是使用UNION ALL 实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
SELECT 
    year,
    'A' AS product,
    A AS sales
FROM sales_data

UNION ALL

SELECT 
    year,
    'B' AS product,
    B AS sales
FROM sales_data;

ORDER BY year, product;
  • 第一个 SELECT 子查询提取了 A 列的数据,并将 A 作为 product 值:
  • 输出行:(2020, 'A', 100)(2021, 'A', 150)
  • 第二个 SELECT 子查询提取了 B 列的数据,并将 B 作为 product 值:
  • 输出行:(2020, 'B', 200)(2021, 'B', 300)
  • UNION ALL 将两组查询结果合并。