SQL实现行转列的两种方式

SQL实现行转列的两种方式

在我们日常开发的场景中,可能会遇到使用SQL进行行转列的问题,那么下面我将介绍两种方式供大家参考。大家只要认真看完,我想肯定会学会这两种简单的方法的!
首先我们准备一张数据表:my_score
代码如下:

CREATE TABLE `my_score` (
  `std` varchar(255) DEFAULT NULL,
  `prj` char(10) DEFAULT NULL,
  `score` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

准备好表之后,我们可以插入几条数据:

insert  into `my_score`(`std`,`prj`,`score`) values ('S1','MATH',90),('S1','ENGLISH',98),('S1','CHINESE',85),('S2','MATH',87),('S2','ENGLISH',78),('S2','CHINESE',89);

这里,我们简单插入两条数据即可。此时,我们表中的数据如下:
SQL实现行转列的两种方式_第1张图片
此时,我们想要进行行转列,得到如下期望的效果:
SQL实现行转列的两种方式_第2张图片
这样,我们将S1、S2对应的三行数据通过行列转换变成一行数据。
那么,如何实现呢?这里为大家提供两种思路:第一种:使用join。
首先,我们可以查出某一科目的成绩,例如:

 SELECT `std`,score as 'MATH' FROM my_score WHERE prj = 'MATH';

查询结果如下:
SQL实现行转列的两种方式_第3张图片
看到这,我想大家也明白了,对,我们把其他几门科目的成绩查出来后当做临时表再使用join不就解决了该问题吗?!而连接条件便是std。看到这,大家可以自己试一试。完整代码如下:

SELECT t1.std,t1.score AS 'MATH',t2.score AS 'ENGLISH',t3.score AS 'CHINESE'
FROM (SELECT `std`,score FROM my_score WHERE prj = 'MATH') AS t1
JOIN
(SELECT `std`,score FROM my_score WHERE prj = 'ENGLISH') AS t2
ON
t1.std = t2.std
JOIN
(SELECT `std`,score FROM my_score WHERE prj = 'CHINESE') AS t3
ON
t1.std = t3.std;

注意:这里std加了反引号为了避免和关键字冲突。

看到这里,大家已经学会了一种行转列的操作,是不是期待下一种方式是什么呢?接下来给大家介绍第二种方式:union all。使用这种方式需要大家知道union和union all的用法。这里简单介绍一下:
union:会将两个结果集进行并集处理,不包括重复的行;
union all:对两个结果集进行并集处理,包括重复行。
知道这两点,就够我们在这的使用。
思路大同小异,我们还是差出一科的成绩,其他科目我们暂且用0代替:

SELECT `std`,score AS 'MATH',0 AS 'ENGLISH',0 AS 'CHINESE' FROM my_score WHERE prj = 'MATH';

代码运行如下:
SQL实现行转列的两种方式_第4张图片
这样我们可以将其他科目也按照这种方式查询出来,并进行union all进行合并。

(SELECT `std`,score AS 'MATH',0 AS 'ENGLISH',0 AS 'CHINESE' FROM my_score WHERE prj = 'MATH')
UNION ALL
(SELECT `std`,0 AS 'MATH',score AS 'ENGLISH',0 AS 'CHINESE' FROM my_score WHERE prj = 'ENGLISH')
UNION ALL
(SELECT `std`,0 AS 'MATH',0 AS 'ENGLISH',score AS 'CHINESE' FROM my_score WHERE prj = 'CHINESE');

结果如下:
SQL实现行转列的两种方式_第5张图片
正如我们所料,这样查询会有很多重复的行,需要我们使用sum()来进行处理(这里就是查询单个科目时使用0代替其他科目的原因,在我们进行sum时不影响我们的结果)最后,整理可以得到我们最终想要的结果:

SELECT `std`,SUM(MATH) AS 'MATH',SUM(ENGLISH) AS 'ENGLISH',SUM(CHINESE)AS CHINESE FROM (
(SELECT `std`,score AS 'MATH',0 AS 'ENGLISH',0 AS 'CHINESE' FROM my_score WHERE prj = 'MATH')
UNION ALL
(SELECT `std`,0 AS 'MATH',score AS 'ENGLISH',0 AS 'CHINESE' FROM my_score WHERE prj = 'ENGLISH')
UNION ALL
(SELECT `std`,0 AS 'MATH',0 AS 'ENGLISH',score AS 'CHINESE' FROM my_score WHERE prj = 'CHINESE')
) tmp GROUP BY `std`;

注意:进行sum()时要记得根据std分组。
以上便是两种行转列的方法,大家可以根据自己的思路习惯来进行选择,union all 的方式思路条理较为清晰,但是代码多些;join大家使用的较多可能会更为容易想到。最后,谢谢大家可以看到这里,学习了一个小技巧,为自己点个赞吧。

你可能感兴趣的:(大数据学习之路,mysql,sql)