更新以在单个语句中切换布尔列

时间:2019-03-22 01:08:43

标签: sql postgresql performance

如何以最有效的方式在单个 sql 语句中组合

UPDATE TABLE_A a
SET a.is_active = FALSE
WHERE a.id IN (SELECT id FROM TABLE_B);

和其余id的标志相同,但 togggle

UPDATE TABLE_A a
SET a.is_active = TRUE
WHERE a.id NOT IN (SELECT id FROM TABLE_B);

4 个答案:

答案 0 :(得分:2)

好吧,您可以使用UPDATE TABLE_A a SET a.is_active = (CASE WHEN a.id IN (SELECT id FROM TABLE_B) THEN FALSE ELSE TRUE END); 表达式:

UPDATE TABLE_A
    SET is_active = (id IN (SELECT b.id FROM TABLE_B b));

在Postgres中,您可以将其简化为:

apt-get

答案 1 :(得分:2)

在Postgres中,您可以在LEFT JOIN语句中使用以下语法使用UPDATE

UPDATE a 
SET a.is_active = CASE WHEN b.id IS NULL THEN FALSE ELSE TRUE
FROM TABLE_A a
LEFT JOIN TABLE_B b ON a.id = b.id

答案 2 :(得分:2)

UPDATE table_a a
SET    is_active = NOT EXISTS (SELECT FROM table_b b WHERE b.id = a.id);

假设两个id列均为 NOT NULL

否则,table_a.id IS NULL既不是NULL也不是IN任何集合,因此在您的原始行中根本没有{strong>未更新的行。

如果NOT IN中有任何NULL个值,则您的行中的都以table_b.id结尾,因为a.is_active = TRUE是{{ 1}}或a.id NOT IN (SELECT id FROM TABLE_B),但在这种情况下永远不要使用FALSENULL因这种“陷阱”而臭名昭著。相关:

带有TRUE的查询会更新所有行。 NOT IN的结果为EXISTS,就像在table_a.id IS NULL中找不到的其他ID一样,is_active = TRUE中的NULL值也没有任何区别。

table_b也很有吸引力,特别是如果table_b.id中可以有(很多)重复值-则性能更好。在任何情况下都应为EXISTS编制索引。

答案 3 :(得分:0)

您可以在两个表上使用联接,然后使用case语句确定表B中是否存在值:

CREATE TABLE #TABLE_A (Id int, is_active bit)
CREATE TABLE #TABLE_B (Id int)


INSERT INTO #Table_A 
    VALUES   (1, NULL)
            ,(2, NULL)
            ,(3, NULL)
            ,(4, NULL)

INSERT INTO #TABLE_B 
    VALUES (1),(3)


SELECT * FROM #TABLE_A

UPDATE a
    SET is_active = (CASE WHEN b.id IS NULL THEN 1 ELSE 0 END)
FROM    #TABLE_A a
            LEFT OUTER JOIN #TABLE_B b
                ON      a.id = b.Id

SELECT * FROM #TABLE_A