Skip to content

Commit 0e02313

Browse files
committed
sql行转列
1 parent 646dd78 commit 0e02313

File tree

1 file changed

+87
-5
lines changed

1 file changed

+87
-5
lines changed

mysql开发技巧二/如何进行行列转化

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SQL开发技巧(二)
99

1010
********************************************************************************
1111
行转列:
12-
利用自身连接来实现:
12+
1.利用自身连接来实现:
1313
SELECT *
1414
FROM (
1515
SELECT SUM(KILLS) AS 'A'
@@ -23,11 +23,93 @@ FROM A INNER JOIN B ON A.NAME=B.USER_NAME
2323
WHERE A.NAME='C')AS C;
2424

2525
比如成绩
26-
1、分别查询出不同同学的成绩,并将字段名改为同学的名字
27-
2、通过交叉连接,将不同的语句连接起来
26+
1、分别查询出不同同学的成绩,并将字段名改为同学的名字
27+
2、通过交叉连接,将不同的语句连接起来
28+
29+
缺点:是将原来查询的结果每一行单独查询出来,再进行拼接。
30+
因此每增加一个同学就增加一个SELECT语句。并且是通过交叉连接,要保证每个查询的结果只能是一个,不然没办法通过交叉连接实现转换。
31+
32+
********************************************************************************
33+
34+
2.使用case语句进行行列转换<br>
35+
select sum(case when user_name='孙悟空' then kills end) as '孙悟空',<br>
36+
sum(case when user_name='猪八戒' then kills end) as '猪八戒',<br>
37+
sum(case when user_name='沙僧' then kills end) as '沙僧'<br>
38+
from user1 a join user_kills b on a.id=b.user_id;
39+
-----------------------------------------------
40+
使用CASE语句:
41+
SELECT SUM(CASE USER_NAME='A' THEN KILLS END) AS 'A',
42+
SUM(CASE USERNAME='B' THEN KILL END) AS 'B',
43+
SUM(CASE USERNAME='C' THEN KILL END) AS 'C'
44+
FROM A INNER JOIN B ON A.NAME=B.USERNAME;
45+
46+
通过CASE给满足WHEN语句的数据返回SUM聚合函数要统计的数据,再将SUM进行重命名。推荐。
47+
一般形式
48+
SELECT NAME AS '姓名',
49+
SUM(CASE SUBJECT WHEN '数学' THEN MARK ELSE NULL END) AS '数学',
50+
SUM(CASE SUBJECT WHEN '英语' THEN MARK ELSE NULL END) AS '英语',
51+
SUM(CASE SUBJECT WHEN '语文' THEN MARK ELSE NULL END) AS '语文'
52+
FROM SUBJECT
53+
GROUP BY NAME;
54+
55+
CASE语句中放原来表中要进行转换的字段(如学科),对其进行分类(如数学、英语、语文)。
56+
注意:要用聚合函数,最后要GROUP BY。
57+
58+
59+
********************************************************************************
60+
列转行:
61+
单列转多行:属性拆分,ETL数据处理
62+
63+
********************************************************************************
64+
利用序列表处理列转行的数据
65+
a.select a.user_name, concat(a.mobile,',') mobile,
66+
length(mobile)-length(replace(a.mobile,',',''))+1 size from user1 a
67+
每一列后面添加‘,’ 并根据‘,’统计出包含的数量
68+
b.和tb_sequence进行cross join 实现size多大就生成几条的记录
69+
70+
c.进行字符串的截取
71+
72+
73+
分享一个序列表的存储过程
74+
DROP PROCEDURE IF EXISTS usp_getseqtable;
75+
CREATE PROCEDURE usp_getseqtable(
76+
IN id INT
77+
)
78+
BEGIN
79+
DECLARE i INT;
80+
DROP TABLE IF EXISTS im_sequence;
81+
CREATE TABLE im_sequence (
82+
id INT AUTO_INCREMENT PRIMARY KEY
83+
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
84+
SET i=1;
85+
WHILE i <= id DO
86+
#插入表数据
87+
INSERT INTO im_sequence VALUES (NULL);
88+
SET i = i + 1;
89+
END WHILE;
90+
END;
91+
92+
CALL usp_getseqtable(20)
93+
94+
********************************************************************************
95+
96+
列转行的场景之二
97+
98+
使用union all连接转换:
99+
select user_name,'arms' as equipment, arms from user1 a join user1_equipment b on a.id=user_id
100+
union all
101+
select user_name,'clothing' as equipment, clothing from user1 a join user1_equipment b on a.id=user_id
102+
union all
103+
select user_name,'shoe' as equipment, shoe from user1 a join user1_equipment b on a.id=user_id
104+
105+
106+
107+
108+
109+
110+
111+
28112

29-
缺点:是将原来查询的结果每一行单独查询出来,再进行拼接。
30-
因此每增加一个同学就增加一个SELECT语句。并且是通过交叉连接,要保证每个查询的结果只能是一个,不然没办法通过交叉连接实现转换。
31113

32114

33115

0 commit comments

Comments
 (0)