如何使用另一行中的值填充所有行中的空列

时间:2015-02-09 12:06:57

标签: mysql

我有这张桌子:

num | id | value1 | value2 | ..... | valueN
____|____|________|________|_______|_______
 1  |  1 |  val1  | val2   | ..... | valN
 2  |  1 |  blah  | NULL   | ..... | NULL
 1  |  2 | val12  | val22  | ..... | valN2
 2  |  2 | blah2  | NULL   | ..... | NULL

numid是主键。包含1 num的每一行都是填充了所有列的行,id的所有其他行(其中num大于1)都有空列我想要填充使用num = 1中具有相同id的列中的相应值。

我可以编写一个在所有num> 1行上运行的脚本,然后在每个空列上运行,并从num = 1行开始运行但是有更多的SQLy方法吗?更一般的东西,没有迭代每一列?

2 个答案:

答案 0 :(得分:1)

好吧,您可以尝试使用cross-table UPDATE JOIN

更新所有行
UPDATE mytbl AS a
INNER JOIN (SELECT * FROM mytbl WHERE num = 1) AS b ON a.id = b.id
SET a.value1 = b.value1,
  a.value2 = b.value2,
...
  a.valueN = b.valueN
WHERE  a.num > 1 

答案 1 :(得分:1)

要更新值(并保留它们,如果已经存在),基本查询将如下所示:

update Table1 t
join (select * from Table1 where num = 1) ones
on t.id = ones.id and t.num != ones.num
set 
    t.value1 = IFNULL(t.value1, ones.value1),
    t.value2 = IFNULL(t.value2, ones.value2),
    t.valueN = IFNULL(t.valueN, ones.valueN);

由于无法执行update tablea from tableb set a.* = b.*,您必须在查询中包含要更新的所有列,如果我理解您的问题,则这是您要避免的确切情况。

使用动态sql并查询数据库的信息模式,可以构建一个更新所有列的更新语句(手动排除的列除外)。

这个方法有点hackish但是应该可行,但它可能效果不好而且可能不安全。

如果将名为Table1的测试表设置为您的示例,则可以运行以下代码来更新除idnum以外的所有列:

-- base update statement
SET @sql:= 'update Table1 t
join (select * from Table1 where num = 1) ones
on t.id = ones.id and t.num != ones.num 
set ';

-- concatenate the base update with the column specific part
SELECT @stmnt := concat(@sql, group_concat(
  't.',
  COLUMN_NAME, 
  ' = IFNULL(t.',
  COLUMN_NAME,'
  , ones.',
  COLUMN_NAME,
  ')'))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Table1'
-- exclude these columns from the update
AND column_name != 'id'
AND column_name != 'num';

-- build a statement and execute it
PREPARE dynamic_statement FROM @stmnt;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement;