此文以一个实际的查询问题为例说明,MySQL中的行转列问题怎么解决。
一、问题
表:student
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| name | varchar |
| continent | varchar |
+-------------+---------+
该表没有主键。它可能包含重复的行。
该表的每一行表示学生的名字和他们来自的大陆。
一所学校有来自亚洲、欧洲和美洲的学生。
写一个查询语句实现对大洲(continent)列的 透视表 操作,使得每个学生按照姓名的字母顺序依次排列在对应的大洲下面。输出的标题应依次为美洲(America)、亚洲(Asia)和欧洲(Europe)。
测试用例的生成使得来自美国的学生人数不少于亚洲或欧洲的学生人数。
查询结果格式如下所示。
示例 1:
输入:
Student table:
+--------+-----------+
| name | continent |
+--------+-----------+
| Jane | America |
| Pascal | Europe |
| Xi | Asia |
| Jack | America |
+--------+-----------+
输出:
+---------+------+--------+
| America | Asia | Europe |
+---------+------+--------+
| Jack | Xi | Pascal |
| Jane | null | null |
+---------+------+--------+
二、思路
第一步:
按照continent分组,按照NAME排序,增加一列,命名为rk。
SELECT *, ROW_NUMBER() OVER (PARTITION BY continent ORDER BY NAME) rk FROM student
第二步:
按照rk分组,max进行 行转列
SELECT
MAX(CASE continent WHEN 'America'THEN NAME ELSE NULL END) AS America,
MAX(CASE continent WHEN 'Asia'THEN NAME ELSE NULL END) AS Asia,
MAX(CASE continent WHEN 'Europe'THEN NAME ELSE NULL END) AS Europe
FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY continent ORDER BY NAME) rk FROM student) t
GROUP BY rk
三、知识点
1.行转列最常见的方法是
group by+sum/max/min(case when)
select * from student_score;
nane subject score
-------------------------------
张三 语文 78
张三 数学 88
张三 英语 98
李四 语文 89
李四 数学 76
李四 英语 90
王五 语文 99
王五 数学 66
王五 英语 91
要求用一条 sql 语句查出如下结果:
姓名 语文 数学 英语
张三 78 88 98
李四 89 76 90
王五 89 56 89
语句为:SELECT NAME,
max( CASE SUBJECT WHEN '语文' THEN score END ) '语文',
max( CASE SUBJECT WHEN '数学' THEN score END ) '数学',
max( CASE SUBJECT WHEN '英语' THEN score END ) '英语'
FROM
student_score
GROUP BY
NAME
2.原表格没有基准id或者基准列需要自己构造,比如上面问题的rk列,相当于知识点第一点举例中的name列。