多个表之间的动态列名导入mySQL

时间:2019-01-01 01:29:17

标签: mysql

我已导入名为book1的表,其表的列名称为:ID,2018M01、2018M02、2018M03

我现在需要导入第二个名为book2的表,其列名称为:ID,2018M05、2018M06、2018M07

两个表中的列名之间有相似的东西,即前缀Yea​​r2018。

如果可能的话,我宁愿不像下面那样继续为每个表的每个列名编写代码的这一部分

CREATE TABLE book1 (
    ID VARCHARACTER(10),
    2018M01 decimal(4,2),
    2018M02 decimal(4,2),
    2018M03 decimal(4,2)
);

实际上,实际表有几列。

下面编写的代码考虑了带有动态节代码的第一个表,但是第二个导入表需要一些帮助。

DROP TABLE IF EXISTS book1;

CREATE TABLE book1 (
    ID VARCHARACTER(10),
    2018M01 decimal(4,2),
    2018M02 decimal(4,2),
    2018M03 decimal(4,2)
);

LOAD DATA LOCAL INFILE '/Users/blytonpereira/Desktop/Book1.csv' REPLACE INTO TABLE book1 
FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 LINES;

SELECT
  GROUP_CONCAT(
    CONCAT(
      'SELECT id, ''', COLUMN_NAME, ''' as month, ', COLUMN_NAME, ' as QTY FROM t1 ') SEPARATOR ' UNION ALL ')
FROM
  `INFORMATION_SCHEMA`.`COLUMNS` 
WHERE
  `COLUMN_NAME` LIKE '2018%'
INTO @sql;

SET @query = CONCAT('select id, month, QTY from (' , @sql , ') x order by id;');

SELECT @query;

 PREPARE stmt FROM @query;
 EXECUTE stmt;

我想避免为每个导入明确定义列名。我正在执行的每个导入都相似但略有不同,即列名每次都会更新。在第一个表中是2018M01..2018M02 ... 2018M03 ....在第二个表中是2018M02..2018M03..2018M04。我需要一些帮助来编写代码的第二部分,其中第二个文件正在导入

1 个答案:

答案 0 :(得分:2)

这只是一个建议,显然没有经过测试,并且有一些固有的假设。

看起来您可以将每个文件加载到SAME表中,因此避免使用动态列名。也就是说,您忽略了我认为其中包含列名称的第一行

LOAD DATA LOCAL INFILE '/Users/blytonpereira/Desktop/Book1.csv' REPLACE INTO TABLE book1 
FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 LINES;

因此可以这样定义“分段”:

CREATE TABLE book_staging (
    ID VARCHARACTER(10),
    MNTH_A decimal(4,2),
    MNTH_B decimal(4,2),
    MNTH_C decimal(4,2)
);

您可以使用这样的参数设置固定查询

set @mnth_a = '2018M04';
set @mnth_b = '2018M05';
set @mnth_c = '2018M06';

select id, month, QTY 
from (
    SELECT id, @mthn_a as month, MNTH_A as QTY FROM book_staging WHERE MNTH_A IS NOT NULL
    UNION ALL 
    SELECT id, @mnth_b as month, MNTH_B as QTY FROM book_staging WHERE MNTH_B IS NOT NULL
    UNION ALL 
    SELECT id, @mnth_b as month, MNTH_C as QTY FROM book_staging WHERE MNTH_C IS NOT NULL
    ) x 
order by id, month
;

在每个加载文件的周期结束时,可以将登台表截断或删除(取决于首选方法),以便为下一次运行做好准备。

就像观察到的那样,列名也是函数名或保留字,使用起来很麻烦。我个人不会使用列名month。同样,我宁愿使用像2018-01-01这样的实际日期,也不愿使用像2018M01这样的字符串,但是使用其他我不知道的字符串可能还有其他原因。