1

我有一个具有以下结构的现有表

+-------------+-------+-------+-------+
| employee_id | val_1 | val_2 | val_3 | ...
+-------------+-------+-------+-------+
|         123 |     A |     B |     C |

我想将这个单个表更改为 2 个表 - 一个包含单独行中的值,另一个包含为此的连接表。例如,上面将变成这样:

+-------------+--------+      +----+-------+
| employee_id | val_id |      | id | value |
+-------------+--------+      +----+-------+
|         123 |      1 |      |  1 |     A |
+-------------+--------+      +----+-------+
|         123 |      2 |      |  2 |     B |
+-------------+--------+      +----+-------+
|         123 |      3 |      |  3 |     C |
+-------------+--------+      +----+-------+

将现有表转换为这两个新表的最佳 SQL 是什么?我可以很容易地创建值表,但我不确定如何同时创建连接表。

4

3 回答 3

1

像这样的东西(仅限伪代码,抱歉):

For each row in (SELECT employee_id, val_1, val_2, val_3 FROM existing_table)
{
   for each val in (row.Values)
   {
     INSERT INTO new_values (val)
     val_id = SELECT LAST_INSERT_ID();
     INSERT INTO new_employees (employee_id, val_id);
  }
}

可能有一种基于集合的方式来避免循环......但对不起,我不知道它像你一样,我不知道如何将值表的身份返回到父级员工表。

而且,虽然游标通常不受欢迎,但这种一次性操作正是它们的设计目的(即,我不建议将游标用于常规事务或报告处理,而是用于数据的重新结构...... .. 为什么不?)。

于 2012-12-24T07:41:09.467 回答
0

所以这就是我最终写的东西。正如程序名称所暗示的那样,我期待有一种更直接的方法来做到这一点!

CREATE PROCEDURE iWasHopingItWouldBeSimpler()
BEGIN
   DECLARE loop_done BOOLEAN DEFAULT 0;

   DECLARE emp_id BIGINT(20);
   DECLARE val1 DECIMAL(19,2);
   DECLARE val2 DECIMAL(19,2);
   DECLARE val3 DECIMAL(19,2);

   DECLARE emp CURSOR
   FOR
   SELECT employee_id, val1, val2, val3 FROM existing;   

   -- Declare continue handler
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET loop_done=1;

   OPEN emp;

   -- Loop through all rows
   REPEAT
      FETCH emp INTO emp_id, val1, val2, val3;

      INSERT INTO new_values (value) VALUES(val1);
      INSERT INTO new_join (employee_id, values_id) VALUES(emp_id, LAST_INSERT_ID());

      INSERT INTO new_values (value) VALUES(val2);
      INSERT INTO new_join (employee_id, values_id) VALUES(emp_id, LAST_INSERT_ID());

      INSERT INTO new_values (value) VALUES(val3);
      INSERT INTO new_join (employee_id, values_id) VALUES(emp_id, LAST_INSERT_ID());

   -- End of loop
   UNTIL loop_done END REPEAT;

   CLOSE emp;
   SET loop_done=0;
END;
于 2012-12-24T09:14:17.963 回答
0

第一个结果

`INSERT INTO new_val
SELECT  emp_id, REPLACE(UPPER(column_name), 'VAL_', '') FROM   
information_schema.COLUMNS ,
employee
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'myschema' AND column_name LIKE 'VAL_%'`;


使用第一个结果,填充查询并使用它插入新表;可能需要进行微调。未测试
SELECT CONCAT('select ', new_val.number, ', VAL_', new_val.number, ' FROM employee, new_val WHERE new_val.emp_id = employee.emp_id and new_val.number = ', val.number, ' union all' ) FROM val ;

于 2012-12-24T07:40:56.243 回答