0

我有一个非规范化格式的大型数据集。以下是列名的示例:

foreign_key_ID, P1, P2, P3, P4, P5.... D1, D2, D3.... 等等..

这些字段都包含相似类型的数据。

我需要将其规范化为我现有的表结构:

insert into new_table (id, name, index)
select foreign_key_id, P1, 1
from denormalized_table;

但这意味着我需要为我的非规范化表中的每个字段运行单独的查询,只需更改一些内容:

insert into new_table (id, name, index)
select foreign_key_id, P2, 2
from denormalized_table;

考虑到我有多少这些领域,这变得越来越乏味。

有没有一种方法可以将其自动化到单个操作中?即:遍历字段(我不介意在某处创建一次合格字段的列表),拉出该字段名称的最后一位(即“P1”中的“1”和“P2”中的“2”)在子选择中使用字段名称和提取的索引#。

4

2 回答 2

1

您正在寻找的是动态 SQL。您可以在此处执行可以以编程方式组合的 SQL 语句。只要您在存储过程中,就可以运行字符串中的任意 SQL 代码。请参阅此链接:如何在 MySQL 存储过程中使用动态 SQL

基本上,您可以使用 mySQL 语句通过迭代一组列来构建字符串。您可以使用 SHOW COLUMNS 语法(请参阅http://dev.mysql.com/doc/refman/5.0/en/show-columns.html)返回一个集合,然后遍历该结果集并构建您的动态查询字符串并执行那样。

SHOW COLUMNS FROM myTable WHERE Field NOT IN (pkey, otherFieldIDontWantToInclude)
于 2013-02-04T19:22:10.580 回答
1

这是一个开始:

SELECT column_name, substr(column_name,2) AS `index`
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

您可以修改该语句中的选择列表,让 MySQL 为您生成语句:

SELECT CONCAT('INSERT INTO new_table (id, name, `index`) SELECT foreign_key_id, '
         ,column_name,', ',substr(column_name,2)
         ,' FROM denormalized_table ;') AS stmt
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

其输出将是一组 MySQL INSERT 语句,然后您可以执行这些语句。


如果要插入的数据的行数和总大小不是太大,您可以并且希望在“一次操作”中完成整个转换,那么您可以生成单个 INSERT INTO ... SELECT 语句,使用 UNION ALL 运算符。我会得到这样的大部分陈述:

SELECT CONCAT('UNION ALL SELECT foreign_key_id, '
         ,column_name,', ',substr(column_name,2)
         ,' FROM denormalized_table ') AS stmt
  FROM information_schema.columns
 WHERE table_schema = 'mydatabasename'
   AND table_name = 'denormalized_table'
   AND column_name REGEXP '^[PD][0-9]+$'
 ORDER BY column_name

我会从中获取输出,并将第一个替换UNION ALLINSERT INTO .... 这将给我一个运行语句来完成整个转换。

于 2013-02-04T19:25:37.140 回答