将MySQL表文本值拆分为多行

时间:2018-08-17 19:06:12

标签: mysql mysql-workbench

我有桌子:

id | room_type     | room_size
1  | a;b;c         | 5;7;12   
2  | b;c;d;f       | 8;2;4
3  | b;c;d;f;g;h   | 6;4;5;6;7;2;9

我想要这样的输出:

id | name    | room_size
1  | a       | 5
1  | b       | 7
1  | c       | 12
2  | b       | 8
2  | c       | 2
2  | d       | 4
2  | f       | NULL
3  | b       | 6
3  | c       | 4
3  | d       | 5
3  | f       | 6
3  | g       | 7
3  | h       | 2

注意:在(id)2中,room_size计数减1。在(id)3中,room_size增大1

1 个答案:

答案 0 :(得分:1)

不存储逗号分隔的值列表。 (这并不意味着使用分号代替逗号。)

SQL反模式:避免数据库编程的陷阱 – Bill Karwin,第2章

可在亚马逊和其他优质书商处购买。

https://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557


对于有限数量的值,我们可以将其拆分为单独的行

(用表格替换内联视图t

SELECT t.id
     , i.n
     , NULLIF(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( t.room_type ,';;'),';',i.n),';',-1),'') AS room_type_n
     , NULLIF(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT( t.room_size ,';;'),';',i.n),';',-1),'') AS room_size_n
  FROM ( SELECT 1 AS id, 'a;b;c' AS room_type, '5;7;12'  AS room_size
         UNION ALL SELECT 2,'b;c;d;f','8;2;4'
         UNION ALL SELECT 3,'b;c;d;f;g;h','6;4;5;6;7;2;9'
       ) t
 CROSS
  JOIN ( SELECT 1 AS n
         UNION ALL SELECT 2
         UNION ALL SELECT 3
         UNION ALL SELECT 4
         UNION ALL SELECT 5
         UNION ALL SELECT 6
         UNION ALL SELECT 7
         UNION ALL SELECT 8
         UNION ALL SELECT 9
       ) i 
HAVING NOT ( room_type_n <=> NULL )
 ORDER BY t.id, i.n

返回:

 id    n  room_type_n  room_size_n
---  ---  -----------  -----------
  1    1  a            5
  1    2  b            7
  1    3  c            12
  2    1  b            8
  2    2  c            2
  2    3  d            4
  2    4  f            (NULL)
  3    1  b            6
  3    2  c            4
  3    3  d            5
  3    4  f            6
  3    5  g            7
  3    6  h            2

内联视图i应该扩展到我们希望提取的有限的最大数量的值:UNION ALL SELECT 10 UNION ALL SELECT 11 ...