mysql - 动态地将列拆分为行

Posted

技术标签:

【中文标题】mysql - 动态地将列拆分为行【英文标题】:mysql - split columns to rows dynamically 【发布时间】:2017-09-19 12:23:08 【问题描述】:

我有表训练,我想将 Training_name 列值拆分为多个行:

SLNO Category Training_name
1     A        1,5,9,15,12,16
2     B        2,6,10,17
3     C        1,3,7,19,14,18

我在下面使用了查询,但是使用这个查询我只能分成两行...

SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', 1) AS TRAINING_NAME FROM training UNION ALL SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', -1) FROM training

我正在尝试获取下面给出的表格,请帮助我

SLNO Category Training_name
1      A        1
1      A        5
1      A        9
1      A        15
1      A        12
1      A        16
2      B        2
2      B        6
2      B        10
2      B        17
3      C        1
3      C        3
3      C        7
3      C        19
3      C        14
3      C        18

【问题讨论】:

希望你想这样做来修复数据结构。 这可能是一次性操作来规范化您的数据,所以一些粗略的代码就可以了。您应该尝试在 php 中执行此操作。 SO 不是代码编写服务,因此您至少应该对此进行一些尝试。 ***.com/questions/17308669/… @etsa:正如我想说的:通过使用 PHP,您可以极大地简化这一过程。 就像***.com/questions/17942508/… 中提出的问题中的这个?? 【参考方案1】:
DROP TABLE IF EXISTS my_bad_table;
DROP TABLE IF EXISTS my_good_table;

CREATE TABLE my_bad_table
(SLNO INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,Category CHAR(1) NOT NULL
,Training_name VARCHAR(200) NOT NULL
);

INSERT INTO my_bad_table VALUES
(1,'A','1,5,9,15,12,16'),
(2,'B','2,6,10,17'),
(3,'C','1,3,7,19,14,18');

CREATE TABLE my_good_table AS
SELECT DISTINCT x.SLNO
              , x.Category
              , CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(x.training_name,',',y.i+1),',',-1) AS UNSIGNED) training_name
           FROM my_bad_table x
              , (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 
                 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 8 UNION SELECT 9) y
          ORDER 
             BY slno
              , category
              , training_name;

SELECT * FROM my_good_table;
+------+----------+---------------+
| SLNO | Category | training_name |
+------+----------+---------------+
|    1 | A        |             1 |
|    1 | A        |             5 |
|    1 | A        |             9 |
|    1 | A        |            12 |
|    1 | A        |            15 |
|    1 | A        |            16 |
|    2 | B        |             2 |
|    2 | B        |             6 |
|    2 | B        |            10 |
|    2 | B        |            17 |
|    3 | C        |             1 |
|    3 | C        |             3 |
|    3 | C        |             7 |
|    3 | C        |            14 |
|    3 | C        |            18 |
|    3 | C        |            19 |
+------+----------+---------------+

如果 1 始终为“A”等,则需要进一步标准化以消除冗余。

【讨论】:

【参考方案2】:

这是一种方法:

select slno, category, substring_index(training_name, ',', 1) + 0 as training_id
from t
union all
select slno, category, substring_index(substring_index(training_name, ',', 2), ',', -1) + 0 as training_id
from t
where training_name like '%,%'
union all
select slno, category, substring_index(substring_index(training_name, ',', 3), ',', -1) + 0 as training_id
from t
where training_name like concat('%', repeat(',%', 2))
union all
select slno, category, substring_index(substring_index(training_name, ',', 4), ',', -1) + 0 as training_id
from t
where training_name like concat('%', repeat(',%', 3))
union all
 . . .

根据需要多次重复。将结果存储在新表中。修复外键引用和数据的其他方面。删除原始表(好吧,将其归档)并且不再使用该结构。

【讨论】:

【参考方案3】:

对我有用..

SELECT DISTINCT x.PARENT_SLNO, x.TRAINING_CATEGORY, CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(x.TRAINING_NAME,',',y.i+1),',',-1) AS UNSIGNED) TRAINING_NAME FROM assessment_training x, (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 8 UNION SELECT 9) y where PARENT_SLNO = 3 and TRAINING_CATEGORY='technical' ORDER BY PARENT_SLNO,TRAINING_CATEGORY,TRAINING_NAME

【讨论】:

以上是关于mysql - 动态地将列拆分为行的主要内容,如果未能解决你的问题,请参考以下文章

SQL:在 Chartio 中动态地将列转换为行

如何将列中的连接值转置为行

Redshift :- 易于将逗号分隔的字符串拆分为行

如何有效地将具有一定周期性的列表拆分为多个列表?

SQL 动态地将值拆分为新列

Postgres 表选择多列并将结果(列)动态转换为行 - 将列转置为行