在Postgres中更新包含不出现在另一个表中的ID的所有行

时间:2013-11-06 16:15:45

标签: sql postgresql

我正在编写SQL代码以从我们的供应商数据库更新我们的产品数据库。为此,我导入供应商数据库。到目前为止一切正常。然后,我运行以下命令来获取我们数据库中可用的所有ID号的列表,但不再列在供应商数据库中:

SELECT id_number
FROM products
WHERE available IS true
EXCEPT
SELECT id_number
FROM supplier_db;

EXPLAIN消息是“SetOp Except(cost = 151027.48..154845.30 rows = 454191 width = 4)”

这在大约1-2秒内运行良好。 EXPLAIN为此命令提供151027.48的成本。但是,我的最终目标是在每个具有此列表中出现的ID号的行上将布尔值available设置为false。所以我使用以下命令:

UPDATE products
SET available = false
WHERE id_number IN (
    SELECT id_number
    FROM products
    WHERE available IS true
    EXCEPT
    SELECT id_number
    FROM supplier_db
);

EXPLAIN消息是“产品更新(成本= 224829.78..279637.52行= 152540宽度= 640)”

但是,第二个命令至少运行15分钟,这是不可接受的。在Postgres有没有办法做到这一点,这将显着加快这一过程?另外,我可能无法正确解释EXPLAIN结果,但是第二个命令不应该只占第一个命令的两倍,考虑到成本只是原来的两倍?

我尝试使用SELECT INTO从第一个SELECT查询创建临时表。它根本没有改变运行时间。此外,id_number在两个表中都被编入索引。

2 个答案:

答案 0 :(得分:1)

如果您运行此查询会怎样?

update products p
set available = false
where available = true
and not exists (select 1 from supplier_db sdb where sdb.id_number = p.id_number)

希望它有所帮助!

答案 1 :(得分:0)

尝试这样或其not exists()变体:

UPDATE products
SET available = false
WHERE available
AND id_number NOT IN (
    SELECT id_number
    FROM supplier_db
);