首页 > 解决方案 > 在 WHERE 条件中使用 UNION 语句插入选择

问题描述

我有一个类似这样的查询:

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`
WHERE `source_table`.`id` IN (
    SELECT DISTINCT `id` FROM `some_table`
    UNION DISTICT SELECT DISTINCT `id` FROM `some_other_table`
);

这不起作用——查询无限期挂起。表的大小绝对不是问题,所有表的记录数都很少(< 100k 记录)。如果我在没有以下命令的情况下运行它,则查询很好并且非常快UNION

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`
WHERE `source_table`.`id` IN (
    SELECT DISTINCT `id` FROM `some_table` -- I tried with `some_other_table` too, same result
);

或者

INSERT IGNORE INTO `destination_table` (`id`, `field1`, `field2`, `field3`)
SELECT `id`, `field1`, `field2`, `field3`
FROM `source_table`

既工作又好又快(不到一秒钟)。所以我想这UNION DISTICT SELECT ...是罪魁祸首,但我不知道为什么。

该查询有什么问题,为什么会挂起?

使用 mysql 5.7 会有所不同

标签: mysql

解决方案


您的第一个查询似乎有一些拼写错误,但我建议在这里使用存在逻辑:

INSERT IGNORE INTO destination_table (id, field1, field2, field3)
SELECT id, field1, field2, field3
FROM source_table t1
WHERE
    EXISTS (SELECT 1 FROM some_table s1 WHERE s1.id = t1.id) OR
    EXISTS (SELECT 1 FROM some_other_table s2 WHERE s2.id = t1.id);

以这种方式使用存在的可能优点是 MySQL 可以id在两个表的任一子查询中找到第一个匹配项时立即停止搜索。您可能会发现id在另外两个列上添加索引会有所帮助(假设id尚未建立索引):

CREATE INDEX some_idx_1 ON some_table (id);
CREATE INDEX some_idx_2 ON some_other_table (id);

这应该加快id在两个依赖表中的查找速度。


推荐阅读