MySQL 将不同列中相同 table 的多值字符串拆分为新的 table
MySQL split multivalued strings from same table in different column into new table
我想将来自一个 table 的 多值 字符串拆分为一个新的 table ,其中包含一个主键和拆分字符串结果。
示例字符串:
table1.field1 (primary key) = 100 , table1.field2 = 'abc,def,ghi'
在新的table(table2)中,结果应该是这样的:
**column1** **column2**
**row1** 100 'abc'
**row2** 100 'def'
**row3** 100 'ghi'
**row4** etc etc
我知道如何拆分table1.field2,但由于数据太大,我需要将结果自动插入到table2中。如果我手动做,会花很长时间。谁能帮帮我?
这是一个使用准备好的语句的解决方案:
DROP TABLE IF EXISTS concatenatedVals;
CREATE TABLE concatenatedVals(`key` INTEGER UNSIGNED, concatenatedValue CHAR(255));
DROP TABLE IF EXISTS splitVals;
CREATE TABLE splitVals(`key` INTEGER UNSIGNED, splitValue CHAR(255));
INSERT INTO concatenatedVals VALUES (100, 'abc,def,ghi'), (200, 'jkl,mno,pqr');
SELECT * FROM concatenatedVals;
SET @VKey := '';
SET @VExec := (SELECT CONCAT('INSERT INTO splitVals VALUES', TRIM(TRAILING ',' FROM GROUP_CONCAT(CONCAT('(', @VKey:= `key`, ', \'', REPLACE(concatenatedValue, ',', CONCAT('\'), (', @VKey, ', \'')), '\'),') SEPARATOR '')), ';') FROM concatenatedVals);
PREPARE stmt FROM @VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT * FROM splitVals;
输出:
SELECT * FROM splitVals;
+------+------------+
| key | splitValue |
+------+------------+
| 100 | abc |
| 100 | def |
| 100 | ghi |
| 200 | jkl |
| 200 | mno |
| 200 | pqr |
+------+------------+
6 rows in set (0.00 sec)
如果您有任何问题,请告诉我。
关于这个问题,我如何解释源中的行数 table 意味着准备好的语句超过 max-concat 长度的情况,请参见以下示例。由于它使用 WHILE
循环,因此它必须在存储过程中。这可以修改为允许 table 名称和列名称作为参数,使用进一步的 CONCAT
AND 准备好的语句来动态构建和执行命令。但是现在,请更改我示例中的 table 和列名称以匹配您的数据,它应该可以正常工作。
DROP TABLE IF EXISTS concatenatedVals;
CREATE TABLE concatenatedVals(`key` INTEGER UNSIGNED, concatenatedValue CHAR(255));
DROP TABLE IF EXISTS splitVals;
CREATE TABLE splitVals(`key` INTEGER UNSIGNED, splitValue CHAR(255));
INSERT INTO concatenatedVals VALUES (100, 'abc,def,ghi'), (200, 'jkl,mno,pqr'),(300, 'abc,def,ghi'), (400, 'jkl,mno,pqr'),(500, 'abc,def,ghi'), (600, 'jkl,mno,pqr'),(700, 'abc,def,ghi'), (800, 'jkl,mno,pqr'),(900, 'abc,def,ghi'), (1000, 'jkl,mno,pqr');
SELECT * FROM concatenatedVals;
DELIMITER $
DROP PROCEDURE IF EXISTS loopStringSplit$
CREATE PROCEDURE loopStringSplit()
BEGIN
DECLARE VKeyMaxLength, VConcatValMaxLength, VFixedCommandLength, VVariableCommandLength, VSelectLimit, VRowsToProcess, VRowsProcessed INT;
SET VFixedCommandLength = CHAR_LENGTH(CONCAT('INSERT INTO splitVals VALUES;'));
SET VKeyMaxLength = (SELECT MAX(CHAR_LENGTH(`key`)) FROM concatenatedVals);
SET VConcatValMaxLength = (SELECT MAX(CHAR_LENGTH(concatenatedValue)) FROM concatenatedVals);
SET VVariableCommandLength = CHAR_LENGTH('(,\'\')');
SET VSelectLimit = FLOOR((@@group_concat_max_len - VFixedCommandLength) / (VKeyMaxLength + VConcatValMaxLength + VVariableCommandLength));
SET VRowsToProcess := (SELECT COUNT(*) FROM concatenatedVals);
SET VRowsProcessed = 0;
SELECT VRowsProcessed, VRowsToProcess, VSelectLimit;
WHILE VRowsProcessed < VRowsToProcess DO
SET @VKey := '';
SET @VExec := (SELECT CONCAT('INSERT INTO splitVals VALUES', TRIM(TRAILING ',' FROM GROUP_CONCAT(CONCAT('(', @VKey:= `key`, ', \'', REPLACE(concatenatedValue, ',', CONCAT('\'), (', @VKey, ', \'')), '\'),') SEPARATOR '')), ';') FROM (SELECT * FROM concatenatedVals LIMIT VRowsProcessed, VSelectLimit) A);
SELECT @VExec;
PREPARE stmt FROM @VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET VRowsProcessed = VRowsProcessed + VSelectLimit;
SELECT CONCAT('Processed rows: ', VRowsProcessed);
END WHILE;
END$
DELIMITER ;
CALL loopStringSplit();
SELECT * FROM splitVals;
此致,
詹姆斯
我想将来自一个 table 的 多值 字符串拆分为一个新的 table ,其中包含一个主键和拆分字符串结果。
示例字符串:
table1.field1 (primary key) = 100 , table1.field2 = 'abc,def,ghi'
在新的table(table2)中,结果应该是这样的:
**column1** **column2**
**row1** 100 'abc'
**row2** 100 'def'
**row3** 100 'ghi'
**row4** etc etc
我知道如何拆分table1.field2,但由于数据太大,我需要将结果自动插入到table2中。如果我手动做,会花很长时间。谁能帮帮我?
这是一个使用准备好的语句的解决方案:
DROP TABLE IF EXISTS concatenatedVals;
CREATE TABLE concatenatedVals(`key` INTEGER UNSIGNED, concatenatedValue CHAR(255));
DROP TABLE IF EXISTS splitVals;
CREATE TABLE splitVals(`key` INTEGER UNSIGNED, splitValue CHAR(255));
INSERT INTO concatenatedVals VALUES (100, 'abc,def,ghi'), (200, 'jkl,mno,pqr');
SELECT * FROM concatenatedVals;
SET @VKey := '';
SET @VExec := (SELECT CONCAT('INSERT INTO splitVals VALUES', TRIM(TRAILING ',' FROM GROUP_CONCAT(CONCAT('(', @VKey:= `key`, ', \'', REPLACE(concatenatedValue, ',', CONCAT('\'), (', @VKey, ', \'')), '\'),') SEPARATOR '')), ';') FROM concatenatedVals);
PREPARE stmt FROM @VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT * FROM splitVals;
输出:
SELECT * FROM splitVals;
+------+------------+
| key | splitValue |
+------+------------+
| 100 | abc |
| 100 | def |
| 100 | ghi |
| 200 | jkl |
| 200 | mno |
| 200 | pqr |
+------+------------+
6 rows in set (0.00 sec)
如果您有任何问题,请告诉我。
关于这个问题,我如何解释源中的行数 table 意味着准备好的语句超过 max-concat 长度的情况,请参见以下示例。由于它使用 WHILE
循环,因此它必须在存储过程中。这可以修改为允许 table 名称和列名称作为参数,使用进一步的 CONCAT
AND 准备好的语句来动态构建和执行命令。但是现在,请更改我示例中的 table 和列名称以匹配您的数据,它应该可以正常工作。
DROP TABLE IF EXISTS concatenatedVals;
CREATE TABLE concatenatedVals(`key` INTEGER UNSIGNED, concatenatedValue CHAR(255));
DROP TABLE IF EXISTS splitVals;
CREATE TABLE splitVals(`key` INTEGER UNSIGNED, splitValue CHAR(255));
INSERT INTO concatenatedVals VALUES (100, 'abc,def,ghi'), (200, 'jkl,mno,pqr'),(300, 'abc,def,ghi'), (400, 'jkl,mno,pqr'),(500, 'abc,def,ghi'), (600, 'jkl,mno,pqr'),(700, 'abc,def,ghi'), (800, 'jkl,mno,pqr'),(900, 'abc,def,ghi'), (1000, 'jkl,mno,pqr');
SELECT * FROM concatenatedVals;
DELIMITER $
DROP PROCEDURE IF EXISTS loopStringSplit$
CREATE PROCEDURE loopStringSplit()
BEGIN
DECLARE VKeyMaxLength, VConcatValMaxLength, VFixedCommandLength, VVariableCommandLength, VSelectLimit, VRowsToProcess, VRowsProcessed INT;
SET VFixedCommandLength = CHAR_LENGTH(CONCAT('INSERT INTO splitVals VALUES;'));
SET VKeyMaxLength = (SELECT MAX(CHAR_LENGTH(`key`)) FROM concatenatedVals);
SET VConcatValMaxLength = (SELECT MAX(CHAR_LENGTH(concatenatedValue)) FROM concatenatedVals);
SET VVariableCommandLength = CHAR_LENGTH('(,\'\')');
SET VSelectLimit = FLOOR((@@group_concat_max_len - VFixedCommandLength) / (VKeyMaxLength + VConcatValMaxLength + VVariableCommandLength));
SET VRowsToProcess := (SELECT COUNT(*) FROM concatenatedVals);
SET VRowsProcessed = 0;
SELECT VRowsProcessed, VRowsToProcess, VSelectLimit;
WHILE VRowsProcessed < VRowsToProcess DO
SET @VKey := '';
SET @VExec := (SELECT CONCAT('INSERT INTO splitVals VALUES', TRIM(TRAILING ',' FROM GROUP_CONCAT(CONCAT('(', @VKey:= `key`, ', \'', REPLACE(concatenatedValue, ',', CONCAT('\'), (', @VKey, ', \'')), '\'),') SEPARATOR '')), ';') FROM (SELECT * FROM concatenatedVals LIMIT VRowsProcessed, VSelectLimit) A);
SELECT @VExec;
PREPARE stmt FROM @VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET VRowsProcessed = VRowsProcessed + VSelectLimit;
SELECT CONCAT('Processed rows: ', VRowsProcessed);
END WHILE;
END$
DELIMITER ;
CALL loopStringSplit();
SELECT * FROM splitVals;
此致,
詹姆斯