MySQL行转列
1.1. 前言
公司的多个系统间的通信是通过接口来实践的。由于历史的遗留的原因,从其他系统传来的订单和商品的信息是一个字符串,在我们这边 "商品ID" 存储的方式是使用 逗号(',')隔开的。最近要在之前保存的业务上增加需求。但是不好对该记录的商品进行关联。因此,为了让改动降到最低,我们有规划了另外一个表用来来存放商品信息,只存放 "商品ID" 和 主表的ID。
1.2. 表的基本结构
改造前表结构:
1
2
3
4
5
6
7
8
|
CREATE
TABLE
orders
(
orders_id
INT
NOT
NULL
AUTO_INCREMENT
COMMENT
'订单ID'
,
good_ids
VARCHAR
(
200
)
NOT
NULL
COMMENT
'商品ID字符串'
,
PRIMARY
KEY
(
orders_id
)
)
;
INSERT
INTO
orders
VALUES
(
NULL
,
'1,2,3,4,5'
)
;
INSERT
INTO
orders
VALUES
(
NULL
,
'11,12,13,14,15'
)
;
INSERT
INTO
orders
VALUES
(
NULL
,
'21,22,23,24,25'
)
;
|
改造后表结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
--
orders
表不变
CREATE
TABLE
orders
(
orders_id
INT
NOT
NULL
AUTO_INCREMENT
COMMENT
'订单ID'
,
good_ids
VARCHAR
(
200
)
NOT
NULL
COMMENT
'商品ID字符串'
,
PRIMARY
KEY
(
orders_id
)
)
;
--
新增订单商品表
CREATE
TABLE
order_goods
(
order_goods_id
INT
NOT
NULL
AUTO_INCREMENT
COMMENT
'订单商品ID'
,
orders_id
INT
NOT
NULL
COMMENT
'订单ID'
,
goods_id
INT
NOT
NULL
COMMENT
'商品ID'
,
PRIMARY
KEY
(
order_goods_id
)
)
;
|
1.3. 实现行转列
这边我们需要借助一个有着ID连续的表(mysql.help_topic)来做关联,以至于能够划分出商品ID。
1
2
3
4
5
6
7
|
SELECT
o
.
orders_id
,
SUBSTRING_INDEX
(
SUBSTRING_INDEX
(
o
.
good_ids
,
','
,
h
.
help_topic_id
)
,
','
,
-
1
)
FROM
orders
AS
o
JOIN
mysql
.
help_topic
AS
h
ON
h
.
help_topic_id
<=
(
LENGTH
(
o
.
good_ids
)
-
LENGTH
(
REPLACE
(
o
.
good_ids
,
','
,
''
)
)
+
1
)
WHERE
help_topic_id
>
0
ORDER
BY
o
.
orders_id
;
|
1.4. 分解SQL进行解释
这边我们的目的是获得商品ID字符串中第二个商品ID。
使用 逗号(',') 分割 good_ids 查看前两个元素(good_id):
1
2
3
4
5
6
7
8
9
10
|
SELECT
o
.
orders_id
,
SUBSTRING_INDEX
(
o
.
good_ids
,
','
,
2
)
FROM
orders
AS
o
;
+
--
--
--
--
--
-
+
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
+
|
orders_id
|
SUBSTRING_INDEX
(
o
.
good_ids
,
','
,
2
)
|
+
--
--
--
--
--
-
+
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
+
|
1
|
1
,
2
|
|
2
|
11
,
12
|
|
3
|
21
,
22
|
+
--
--
--
--
--
-
+
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
+
|
通过上面获得的前两个元素的字符串,再次进行 逗号(',') 分割,并获得最后一个元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
SELECT
o
.
orders_id
,
SUBSTRING_INDEX
(
SUBSTRING_INDEX
(
o
.
good_ids
,
','
,
2
)
,
','
,
-
1
)
AS
good_id
FROM
orders
AS
o
;
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
orders_id
|
good_id
|
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
1
|
2
|
|
2
|
12
|
|
3
|
22
|
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
最终的SQL只是将指定的第二个元素,变成动态改变的。而动态的改变的数字就是通过关联mysql.help_topic来实现的
小提示:这里使用mysql.help_topic的原因是它有从0到629连续不断的help_topic_id。当然你也可以自己创建一个表并且插入连续不断的数据来作为关联表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
SELECT
o
.
orders_id
,
SUBSTRING_INDEX
(
SUBSTRING_INDEX
(
o
.
good_ids
,
','
,
h
.
help_topic_id
)
,
','
,
-
1
)
AS
good_id
FROM
orders
AS
o
JOIN
mysql
.
help_topic
AS
h
ON
h
.
help_topic_id
<=
(
LENGTH
(
o
.
good_ids
)
-
LENGTH
(
REPLACE
(
o
.
good_ids
,
','
,
''
)
)
+
1
)
WHERE
help_topic_id
>
0
ORDER
BY
o
.
orders_id
;
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
orders_id
|
good_id
|
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
1
|
1
|
|
1
|
2
|
|
1
|
3
|
|
1
|
4
|
|
1
|
5
|
|
2
|
15
|
|
2
|
11
|
|
2
|
12
|
|
2
|
13
|
|
2
|
14
|
|
3
|
22
|
|
3
|
23
|
|
3
|
24
|
|
3
|
25
|
|
3
|
21
|
+
--
--
--
--
--
-
+
--
--
--
--
-
+
|
提示:如果你对编程语言熟悉,也可以使用编写程序解析good_ids保存的方式来做。
昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)
感觉本文内容不错,读后有收获?
逛逛衣服店,鼓励作者写出更好文章。
收 藏
成长的对话版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!