对不起伙计们,我不知道怎么说这个,但我在where子句中有以下内容:
person_id not in (
SELECT distinct person_id
FROM protocol_application_log_devl pal
WHERE pal.set_id = @set_id
)
当子查询没有返回结果时,我的整个select都无法返回任何内容。为解决此问题,我将子查询中的person_id
替换为isnull(person_id, '00000000-0000-0000-0000-000000000000')
。
它似乎有效,但是有更好的方法来解决这个问题吗?
答案 0 :(得分:6)
最好还是使用NOT EXISTS
:
WHERE NOT EXISTS(
SELECT 1 FROM protocol_application_log_devl pal
WHERE pal.person_id = person_id
AND pal.set_id = @set_id
)
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
我看到的模式很多,并且希望我没有,不是。什么时候 我看到这种模式,我畏缩。但不是出于性能原因 - 之后 总之,在这种情况下,它创造了一个足够好的计划:
主要问题是如果目标,结果可能会令人惊讶 column NULLable (SQL Server将此处理为左反半 join,但不能可靠地告诉你右边的NULL是否相等 至 - 或不等于 - 左侧的参考)。也, 如果列可以为NULL,则优化可以表现不同,即使 它实际上不包含任何NULL值
而不是NOT IN,对此查询模式使用相关的NOT EXISTS 。 始终即可。其他方法可以在性能方面与竞争对手相媲美 其他变量是相同的,但所有其他方法都引入 无论是性能问题还是其他挑战。
答案 1 :(得分:2)
虽然我支持Tim的答案是正确的(在这里
警告:子查询或表达式返回的任何空值,使用IN或NOT IN与test_expression进行比较,返回UNKNOWN。 将空值与IN或NOT IN一起使用会产生意外结果 1 。
这就是isnull
“修复”问题的原因 - 它会屏蔽任何此类NULL值并避免意外行为。考虑到这一点,以下方法也可行(但请注意不使用NOT IN开头的建议):
person_id not in (
SELECT distinct person_id
FROM protocol_application_log_devl pal
WHERE pal.set_id = @set_id
AND person_id NOT NULL -- guard here
)
但是,NULL person_id是可疑的并且可能表示其他问题..
1 以下是证明布丁:
select case when 1 not in (2) then 1 else 0 end as r1,
case when 1 not in (2, NULL) then 1 else 0 end as r2
-- r1: 1, r2: 0
答案 2 :(得分:0)
我只是使用null
函数将isnull
值替换为空值,如下例所示。它解决了我的问题
where isnull(UserId,'') not in (select UserID from users where ...)
答案 3 :(得分:0)
这应该有效:
nvl(person_id, '') not in (
SELECT distinct person_id
FROM protocol_application_log_devl pal
WHERE pal.set_id = @set_id
)