数据库:通过SQL语句实现行转列和列转行功能
一、问题
平时工作中我们经常遇到这样的问题,我们在创建数据表的时候是根据业务实际情况设计的,但随着业务的拓展和需求的变化以前我们是通过横向去使用、分析这张表的,后来慢慢的从纵向去分析了,这里我举个例子就明白了。比如公司采购部有两位同事,总共采购四件物品,从采购员角度最终我们的建表语句如下:create table tb_rowcol(name varchar(20),item varchar(20),amount int);
但在实际分析过程中我们需要知道Ada和Bob两位同事各自采购物品的比较和总数,当然通过SELECT…WHERE…方法可以实现,但是有没有更可视化的实现方法呢,也就是说能不能根据item下面的行的内容[Apple,Banana,Orange,Pear]作为列来显示的,这就是行转列的问题。
二、行转列
在MySQL中我们主要通过SUM IF来实现,具体实现语句如下:
mysql> SELECT IFNULL(name,‘Total’) AS name,
-> SUM(IF(item=‘Apple’,amount,0)) AS Apple,
-> SUM(IF(item=‘Banana’,amount,0)) AS Banana,
-> SUM(IF(item=‘Orange’,amount,0)) AS Orange,
-> SUM(IF(item=‘Pear’,amount,0)) AS Pear,
-> SUM(amount) AS total_amount
-> FROM tb_rowcol
-> GROUP BY name WITH ROLLUP;
最终实现的效果如下:
三、列转行
列转行就相当于刚才过程的逆过程,建表语句如下:create table tb_colrow(name varchar(20),Apple int,Banana int,Orange int,Pear int);
,插入相应的数值,最终显示内容如下:
在实现列转行的过程中,我们主要采用UNION ALL拼接各自内容的方式,具体语句如下:
mysql> SELECT name,‘Apple’ AS item,Apple AS amount FROM tb_colrow
-> UNION ALL
-> SELECT name,‘Banana’ AS item,Banana AS amount FROM tb_colrow
-> UNION ALL
-> SELECT name,‘Orange’ AS item,Orange AS amount FROM tb_colrow
-> UNION ALL
-> SELECT name,‘Pear’ AS item,Pear AS amount FROM tb_colrow
-> ORDER BY name;
执行上面的语句,最终实现效果如下:
四、补充
以上是在MySQL数据库中实现的,如果是SQL Server数据,那就更简单了,因为SQL Server提供了行转列、列转行关键字PIVOT、UNPIVOT,如果是在SQL Server数据库环境下,上面需要实现的功能可以这么通过以下代码实现。
行转列:SELECT * FROM tb_rowcol PIVOT (MAX (amount) FOR item IN (Apple,Banana,Orange,Pear) ) a;
列转行:SELECT name,item,amount FROM tb_colrow UNPIVOT (amount FOR item IN ([Apple],[Banana],[Orange], [Pear])) t;
最终实现的效果跟在MySQL是一样的,笔者这里就没去截图了。