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

Posted

技术标签:

【中文标题】更新以在单个语句中切换布尔列【英文标题】:Update to toggle a boolean column in a single statement 【发布时间】:2019-03-22 01:08:42 【问题描述】:

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

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

同样,但切换其余ids的标志:

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

【问题讨论】:

您的第二个查询不会切换值,它只是将其设置为 true。 【参考方案1】:

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

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】:

好吧,你可以使用CASE 表达式:

UPDATE TABLE_A a
    SET a.is_active = (CASE WHEN a.id IN (SELECT id FROM TABLE_B)
                            THEN FALSE ELSE TRUE
                       END); 

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

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

【讨论】:

【参考方案3】:
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 也不是NOT IN 任何集合。

如果table_b.id 中有任何NULLnone 您的行以a.is_active = TRUE 结尾,因为a.id NOT IN (SELECT id FROM TABLE_B)FALSENULL 但绝不是@ 987654336@ 在这种情况下。 NOT IN 因这种“陷阱”而臭名昭著。相关:

Find records where join doesn't exist Select rows which are not present in other table

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

EXISTS 也很有吸引力,特别是如果table_b.id 中可以有(许多)重复值 - 更好的性能。 table_b.id 无论如何都应该被索引。

【讨论】:

【参考方案4】:

您可以在两个表上使用连接,然后使用 case 语句来确定 TABLE 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

【讨论】:

以上是关于更新以在单个语句中切换布尔列的主要内容,如果未能解决你的问题,请参考以下文章

Swift 模式匹配 - 在单个语句中切换、向下转换和可选绑定

React JS - 切换布尔值

MySQL查询以在单个列中查找相似值

Reload Activity 以在 Fragment 之间重新切换

基于布尔值有条件地切换组件属性的值

如何在 DB2 的单个更新语句中更新多个列