SQL Server“不在”子句中的结果无效

SQL Server“不在”子句中的结果无效,sql,sql-server,tsql,Sql,Sql Server,Tsql,我在SQL Server 2012上运行了一个查询,但未返回任何结果。我发现这是不正确的,我应该得到16条记录。我更改了查询并得到了预期的答案,但我不明白为什么我原来的查询没有按预期工作 因此,我最初的查询没有返回任何结果: SELECT WPB.[ID number] FROM [Fact].[REPORT].[WPB_LIST_OF_IDS] WPB WHERE [ID number] NOT IN (SELECT DISTINCT IdNumber

我在SQL Server 2012上运行了一个查询,但未返回任何结果。我发现这是不正确的,我应该得到16条记录。我更改了查询并得到了预期的答案,但我不明白为什么我原来的查询没有按预期工作

因此,我最初的查询没有返回任何结果:

SELECT
    WPB.[ID number]
FROM
    [Fact].[REPORT].[WPB_LIST_OF_IDS] WPB
WHERE
    [ID number] NOT IN (SELECT DISTINCT IdNumber 
                        FROM MasterData.Dimension.Customer DC)
修改后的查询如下所示:

SELECT
    WPB.[ID number]
FROM
    [Fact].[REPORT].[WPB_LIST_OF_IDS] WPB
LEFT JOIN
    MasterData.Dimension.Customer DC ON WPB.[ID number] = DC.IdNumber
WHERE
    DC.IdNumber IS NULL
有人能告诉我为什么第一个查询在几分之一秒的时间内运行,而第二个查询需要一分钟的时间却不起作用?我不想在将来重蹈覆辙

不要在子查询中使用not in。对于空值,它的工作方式与您期望的不同。如果子查询返回的任何值为NULL,则不返回任何行

相反,使用不存在。这具有您期望的语义:

select wpb.[ID number]
from [Fact].[REPORT].[WPB_LIST_OF_IDS] wpb
where not exists (select 1
                  from MasterData.Dimension.Customer dc
                  where wpb.[ID number] = dc.IdNumber
                 );
当然,left join方法也可以使用。

不要在子查询中使用not in。对于空值,它的工作方式与您期望的不同。如果子查询返回的任何值为NULL,则不返回任何行

相反,使用不存在。这具有您期望的语义:

select wpb.[ID number]
from [Fact].[REPORT].[WPB_LIST_OF_IDS] wpb
where not exists (select 1
                  from MasterData.Dimension.Customer dc
                  where wpb.[ID number] = dc.IdNumber
                 );

当然,left join方法也可以使用。

第二个查询也不起作用。如果需要1分钟,则表示缺少索引-一个或两个ID字段都没有索引。在任何情况下,如果您需要SQL方面的帮助,您应该提供表模式、索引、示例数据和所需的输出。如果您需要性能方面的帮助,您应该首先检查执行计划,而不是在“选择不同…”。。。distinct在这里是冗余的,可能会影响性能。无论如何,由于查询的逻辑不同,性能也会有所不同。如果您不想在将来重复这个错误,那么不要在子查询中使用NOT。从不顺便说一句,Select distinct IdNumber会导致不必要的distinct操作。您不关心返回了多少个1,您只关心是否有或没有。查询优化器要么忽略该distinct*,要么最终执行无用的排序/distinct操作。如果维度表中的*any*IdNumber`项为空,则会出现非常严重的问题。维度不应该有空值,它们应该有丢失的、不适用的、未找到的值的显式记录。同样,如果没有模式和数据,人们只能猜测第二个查询也不起作用。如果需要1分钟,则表示缺少索引-一个或两个ID字段都没有索引。在任何情况下,如果您需要SQL方面的帮助,您应该提供表模式、索引、示例数据和所需的输出。如果您需要性能方面的帮助,您应该首先检查执行计划,而不是在“选择不同…”。。。distinct在这里是冗余的,可能会影响性能。无论如何,由于查询的逻辑不同,性能也会有所不同。如果您不想在将来重复这个错误,那么不要在子查询中使用NOT。从不顺便说一句,Select distinct IdNumber会导致不必要的distinct操作。您不关心返回了多少个1,您只关心是否有或没有。查询优化器要么忽略该distinct*,要么最终执行无用的排序/distinct操作。如果维度表中的*any*IdNumber`项为空,则会出现非常严重的问题。维度不应该有空值,它们应该有丢失的、不适用的、未找到的值的显式记录。同样,如果没有模式和数据,人们只能猜测Gordon的答案总是领先几秒钟。只是为了解释为什么不在。它被转换为AND语句,因此不在value1、value2中的列NULL将被转换为列value1、列value2和列NULL,这样您将gt TRUE、TRUE和FALSE,因为列NULL总是FALSE。@DmitrijKultasev:非常精确,挑剔地精确:如果ANSI_NULLS为“是”-否,我不知道他们为什么不把这个命名为空。在实践中,这种区别是不相关的,因为我不知道任何上下文中,未知的内容不会被视为错误。当然,T-SQL没有单独的布尔数据类型可用于存储和观察结果。Gordon总是提前几秒钟回答问题。只是为了解释为什么不在。它被转换为AND语句,因此不在value1、value2中的列NULL将被转换为列value1、列value2和列NULL,这样您将gt TRUE、TRUE和FALSE,因为列NULL总是FALSE。@DmitrijKultasev:非常精确,挑剔地精确:如果ANSI_NULLS为“是”-否,我不知道他们为什么不把这个命名为空。在实践中,这种区别是不相关的,因为我不知道任何上下文中,未知的内容不会被视为错误。当然,T-SQL没有单独的布尔数据类型,可以用来存储和观察结果。