首页 > 解决方案 > UPDATE 中的 CASE 会产生意想不到的结果。移至 WHERE 子句时已修复。为什么?

问题描述

我创建了一个查询来更新标志,我使用 CASE 语句来确定值。但是,当我将查询作为 UPDATE 语句运行时,只有大约一半的预期行被更新?更有趣的是,我之前对相同的数据运行了完全相同的 UPDATE 查询,并且它按预期工作(查看旧与新是导致我调查的原因)。

我尝试使用相同的 CASE 语句进行 SELECT 查询,我得到了正确的结果,但是将其切换回 UPDATE 只会更新大约一半的记录。

将条件移至 WHERE 子句解决了该问题。似乎是 SET 部分中的 CASE 语句导致了问题。我想不通为什么?我想知道这样可以避免将来我犯的任何错误。

原始代码:

UPDATE D
SET PUBLISH_FLAG =
CASE WHEN
         MAPPED_CAT NOT IN(1,2,3)
    AND SRC != '999'
    AND RECEIVED_DATE is not null
    AND RECEIVED_DATE <= D.CENSUS_DATE
    AND SCHEDULED_FLAG = 'N'
    THEN 'Y'
    ELSE 'N'
END
FROM TBL_DATA D
INNER JOIN TBL_PUBLISH V
    ON D.ID = V.ID
    AND D.CENSUS_DATE = V.CENSUS_DATE
    AND D.VERSION_NUMBER = V.VERSION_NUMBER
LEFT JOIN TBL_CAT_MAP C
       ON D.SRC_CATEGORY = C.SOURCE_CAT 

工作代码:

UPDATE D
SET PUBLISH_FLAG = 'Y'
FROM TBL_DATA D
INNER JOIN TBL_PUBLISH V
    ON D.ID = V.ID
    AND D.CENSUS_DATE = V.CENSUS_DATE
    AND D.VERSION_NUMBER = V.VERSION_NUMBER
LEFT JOIN TBL_CAT_MAP C
    ON D.SRC_CATEGORY = C.SOURCE_CAT 
WHERE
         MAPPED_CAT NOT IN(1,2,3)
    AND SRC != '999'
    AND RECEIVED_DATE is not null
    AND RECEIVED_DATE <= D.CENSUS_DATE
    AND SCHEDULED_FLAG = 'N'

我认为两者都应该产生完全相同的结果?我错过了什么?

为了帮助澄清下面的代码有 2 个显示差异,“PUBLISH_FLAG”列(使用我的原始代码或 PSK 的答案更新)有 10162 个“Y”值(其余的“N”),pub_2 列有正确的 18917' Y' 值。

SELECT
PUBLISH_FLAG,
CASE WHEN
         MAPPED_CAT NOT IN(1,2,3)
    AND SRC != '999'
    AND RECEIVED_DATE is not null
    AND RECEIVED_DATE <= D.CENSUS_DATE
    AND SCHEDULED_FLAG = 'N'
    THEN 'Y'
    ELSE 'N'
END as pub_2
FROM TBL_DATA D
INNER JOIN TBL_PUBLISH V
    ON D.ID = V.ID
    AND D.CENSUS_DATE = V.CENSUS_DATE
    AND D.VERSION_NUMBER = V.VERSION_NUMBER
LEFT JOIN TBL_CAT_MAP C
    ON D.SRC_CATEGORY = C.SOURCE_CAT 
WHERE
CASE WHEN
         MAPPED_CAT NOT IN(1,2,3)
    AND SRC != '999'
    AND RECEIVED_DATE is not null
    AND RECEIVED_DATE <= D.CENSUS_DATE
    AND SCHEDULED_FLAG = 'N'
    THEN 'Y'
    ELSE 'N'
END = 'Y'

标签: sqlsql-servertsql

解决方案


两个查询都不相同,在第一个查询中,switch case 中所有不匹配的记录将被设置为 ' N',而不管它们的当前状态如何。

对于仅更新所需记录的此类场景,第二个查询是正确的方法。

您可以更改您的第一个查询,如下所示,以避免更改不匹配的记录。

UPDATE D
SET PUBLISH_FLAG =
CASE WHEN
         MAPPED_CAT NOT IN(1,2,3)
    AND SRC != '999'
    AND RECEIVED_DATE is not null
    AND RECEIVED_DATE <= D.CENSUS_DATE
    AND SCHEDULED_FLAG = 'N'
    THEN 'Y'
    ELSE PUBLISH_FLAG --Modified
END
FROM TBL_DATA D
INNER JOIN TBL_PUBLISH V
    ON D.ID = V.ID
    AND D.CENSUS_DATE = V.CENSUS_DATE
    AND D.VERSION_NUMBER = V.VERSION_NUMBER
LEFT JOIN TBL_CAT_MAP C
       ON D.SRC_CATEGORY = C.SOURCE_CAT 

注意:在上面的查询中,我更改了 else 部分。


推荐阅读