SQL IN 工作但 NOT IN 不起作用

Posted

技术标签:

【中文标题】SQL IN 工作但 NOT IN 不起作用【英文标题】:SQL IN working but NOT IN does not work 【发布时间】:2013-03-13 18:18:45 【问题描述】:

我有这个查询将正确返回属于IN 子句的值,但是当我将其更改为NOT IN 时,它不会返回任何内容。 有人有什么建议吗?

select distinct 
    CAST( w.work_area AS CHAR(4) ) || s.code_id as WATT 
from 
    sys_code s, 
    work_area_master w 
where 
    s.code_type = '590' 
    and (
        CAST( w.work_area AS CHAR(4)) || s.code_id
    )  
    in (
        select substr(misc_flags, 1,6) 
        from sys_code where code_type = 'STA'
    );

【问题讨论】:

提示:NULL 将使 IN 的行为与您的预期不同。 NULLs 正在弄乱您的结果,或者每一行都在该选择中 FROM sys_code s, work_area_master w 看起来不相关。 Mybe,您想在某个通用键域上加入它们吗? 【参考方案1】:

当 A 可能为 NULL 时,排除原则(即 A 或 ~A 是重言式)并不适用。当存在可空字段时,应用三值 loigc,并且必须将排除原则修改为( A 或 ~A 或 A 为 NULL)。

【讨论】:

【参考方案2】:
SELECT DISTINCT
    CAST( w.work_area AS CHAR(4) ) || s.code_id AS what 
FROM sys_code s
JOIN work_area_master w ON 1=1 
WHERE s.code_type = '590' 
AND EXISTS (
    SELECT * FROM sys_code xx
    WHERE xx.code_type = 'STA'
    AND substr(xx.misc_flags, 1,6) = CAST( w.work_area AS CHAR(4)) || s.code_id
    );

脚注:我故意使用JOIN ... ON 1=1 语法来提醒大家注意原来的查询甚至没有连接条件(除了correlated IN 子查询中的那个)

【讨论】:

如果您要进行交叉连接,请使用 CROSS JOIN 语法编写一个。不要加入 1=1 为什么?这个更突出(我仍然不知道OP是否打算做一个carhesian产品,除了子查询) EXISTS >> IN。我冒昧地把它变成了一个合适的CROSS JOIN - 我希望你没问题。 我讨厌语法糖。对我来说1=1 比所有的模糊词更容易阅读。 抱歉打扰了,如果您不同意,请回滚更改。不过,我确实认为使用正确的CROSS JOIN 会更好。【参考方案3】:

检查sys_codework_area_master的组合是否有效实际上可以JOIN条件。

同时使用EXISTS 而不是IN 来避免NULL 出现问题,例如@wilplasser already provided:

SELECT DISTINCT
       CAST( w.work_area AS CHAR(4) ) || s.code_id AS what 
FROM   sys_code s
JOIN   work_area_master w ON EXISTS (
          SELECT 1
          FROM   sys_code x
          WHERE  x.code_type = 'STA'
          AND    substr(x.misc_flags, 1,6)
                 = CAST(w.work_area AS CHAR(4)) || s.code_id
          )
WHERE  s.code_type = '590' ;

有关NOT INNULL 问题的详细说明,请参阅此closely related question on dba.SE。

【讨论】:

【参考方案4】:

可以包含这样的合并函数:

select distinct CAST( w.work_area AS CHAR(4) ) || s.code_id as WATT
from sys_code s, work_area_master w
where s.code_type = '590' 
and (CAST( w.work_area AS CHAR(4)) || s.code_id) in (
select substr(coalesce(misc_flags,"    "), 1,6)
from sys_code
where code_type = 'STA'
);

【讨论】:

不鼓励使用隐式连接的 SQL 反模式。在这种情况下,他似乎有一个交叉连接,这可能是也可能不是他想要的,下一个维护它的人不会知道这是一个错误还是故意的。如果以后的更改添加了额外的 code_type,这尤其危险。 我同意 HLGEM 的观点。但是,如果这是程序员的故意,一些交叉连接可以完全实现。这就是为什么我坚信最好的做法之一是对代码进行评论,而不是让其他人了解作者创建此类代码的意图。 如果您使用显式连接,则只有编写一个交叉连接才能使用。这就是为什么隐式连接是一个非常糟糕的主意的原因之一,如果你打算这样做,因为你的意图不明确。即使您发表评论,cmets 也经常过时,以至于许多开发人员不会意识到它仍然是相关的。如果你使用代码,意图总是很明确的。 出色的 HLGEM!感谢您指出这一点。我会期待自己的代码来避免这样的陷阱。

以上是关于SQL IN 工作但 NOT IN 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PL SQL 从 SQL Dev 工作。但不是来自代码

SQL 维护清理任务工作但不删除

SQL语法异常 - 无效字符,但查询工作正常

SQL 命令 INSERT 正在工作,但数据未出现在表中

SQL 命令 INSERT 正在工作,但数据未出现在表中

为啥 read.csv2 工作得很好,但 read.csv2.sql 显示错误/警告?