为什么在子查询中筛选NULL不起作用?我希望通过将NULL添加到允许的值列表中来获得正确的结果,例如:
SELECT ERP_ServiceProcess.fiStatusNew, RMA.IdRMA
FROM ERP_ServiceProcess RIGHT OUTER JOIN
RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA
WHERE (ERP_ServiceProcess.fiStatusNew IN (NULL, 1, 7, 8))
order by ERP_ServiceProcess.fiStatusNew这给出了不正确的结果,因为RMA中在子表ERP_ServiceProcess(其中ERP_ServiceProcess.fiStatusNew为NULL)中没有记录的所有记录都将被删除。
我必须使用这个(慢)查询来获得正确的结果:
SELECT ERP_ServiceProcess.fiStatusNew, RMA.IdRMA
FROM ERP_ServiceProcess RIGHT OUTER JOIN
RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA
WHERE (ERP_ServiceProcess.fiStatusNew IS NULL)
OR (ERP_ServiceProcess.fiStatusNew IN (1, 7, 8))
order by ERP_ServiceProcess.fiStatusNew尽管我使用了RIGHT OUTER JOIN并且已经向子查询添加了NULL,但是为什么我必须使用第二个慢查询呢?
提前谢谢你。
发布于 2011-02-14 17:19:18
它不会像您预期的那样工作,因为它被扩展为一堆equals操作
fiStatusNew = NULL OR fiStatusNew = 1 OR fiStatusNew = 7 OR fiStatusNew = 8
而anything = NULL是未知的。
考虑到这种扩展,没有特别的理由认为使用IS NULL添加额外的OR本身会降低速度(额外的谓词可能会更改查询计划以使用不同的访问路径,如果统计数据使它相信匹配的行数足以保证这一点的话)
您可以在CASE操作中看到相同的行为
SELECT CASE NULL WHEN NULL THEN 'Yes' ELSE 'No' END /*Returns "No"*/这就是为什么你应该特别注意逆操作NOT IN的原因之一。如果列表包含任何NULL值,您将始终得到一个空的结果集。
fiStatusNew NOT IN (NULL, 1,2)
将扩展为
fiStatusNew<> NULL and fiStatusNew<> 1 and fiStatusNew<> 2
或
Unknown And True/False/Unknown And True/False/Unknown
在three valued logic下,它的计算结果始终为Unknown。
发布于 2011-02-14 17:17:27
你能试着用
ISNULL(ERP_ServiceProcess.fiStatusNew,0) IN (0, 1, 7, 8)未经测试,但可能比第二个查询更快。
发布于 2011-02-14 17:19:47
“ERP_ServiceProcess.fiStatusNew IN (NULL)”的计算结果为“ERP_ServiceProcess.fiStatusNew=NULL”,并且始终为false。在sql server中,NULL被定义为'unknown',而不是‘not’。这就是为什么NULL = NULL或NULL = @var (*)总是计算为false的原因。如果你有两个未知数,你不能检查它们是否相等。只有“is NULL”有效。
(*)嗯,对于sql server,您可以将ANSI_NULLS 设置为off,但并不推荐这样做,因为这不是标准的sql行为。
https://stackoverflow.com/questions/4990452
复制相似问题