前期准备数据以及要求分析:
--创建表
CREATE TABLE tb(`cname` VARCHAR(10),cource VARCHAR(10),score INT) ENGINE=INNODB;
--插入数据
INSERT INTO tb VALUES('张三','语文',74);
INSERT INTO tb VALUES('张三','数学',83);
INSERT INTO tb VALUES('张三','物理',93);
INSERT INTO tb VALUES('李四','语文',74);
INSERT INTO tb VALUES('李四','数学',84);
INSERT INTO tb VALUES('李四','物理',94);
原始表
姓名 | 科目 | 成绩 |
---|---|---|
张三 | 语文 | 74 |
张三 | 数学 | 83 |
张三 | 物理 | 93 |
李四 | 语文 | 74 |
李四 | 数学 | 84 |
李四 | 物理 | 94 |
想要实现结果
姓名 | 语文 | 数学 | 物理 |
---|---|---|---|
张三 | 74.00 | 83.00 | 93.00 |
李四 | 74.00 | 84.00 | 94.00 |
方式一:利用SUM(IF()) 生成列
SELECT
cname AS "姓名",
SUM(IF(cource="语文", score, 0)) AS "语文",
SUM(IF(cource="数学", score, 0)) AS "数学",
SUM(IF(cource="物理", score, 0)) AS "物理"
FROM tb
GROUP BY cname
方式二:利用max(CASE … WHEN … THEN … ELSE END) AS "语文"的方式来实现
SELECT
cname AS "姓名",
MAX(CASE cource WHEN "语文" THEN score ELSE 0 END) AS "语文",
MAX(CASE cource WHEN "数学" THEN score ELSE 0 END) AS "数学",
MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理"
FROM tb
GROUP BY `cname`
分析:
查询:
SELECT * FROM tb GROUP BY cname
结果:
姓名cname | 科目cource | 成绩 |
---|---|---|
张三 | 语文 | 74 |
李四 | 语文 | 74 |
总结一:
行转列,分组(GROUP BY)的列必须是除需要行转列之外的业务主键。
例如tb表中业务主键应该是cname和cource,但是cource需要进行行转列,所以需要按照cname分组。