2016-05-17 46 views
4

由于某些原因,这两个SQL语句不等效。任何人都可以帮助理解为什么吗?在mySQL中IN/NOT IN的使用

SELECT N, IF(P IS NULL, 'Root', IF(N NOT IN (SELECT P FROM BST), 'Leaf', 'Inner')) 
FROM BST 
ORDER BY N; 

SELECT N, IF(P IS NULL, 'Root', IF(N IN (SELECT P FROM BST), 'Inner', 'Leaf')) 
FROM BST 
ORDER BY N; 

P.S. - 这是HackerRank上的二叉搜索树问题。 https://www.hackerrank.com/challenges/binary-search-tree-1

+0

NOT IN(null)欺骗了许多用户。 – jarlh

回答

2

上面的jarlh的评论是正确的,即除了测试IFNULL或'null'之外,没有什么比较TRUE和NULL。所以如果查询:

(SELECT P FROM BST) 

返回单个NULL值,这两个SQL语句将返回不同的结果。这可以很容易地与以下两个SQL语句证明:

select if (1 in (select null), 'a', 'b') => 'b' 

select if (1 not in (select null), 'b', 'a') => 'a' 
0

没有。当基础表具有NULL值时,NOT IN具有奇怪的语义。在这种情况下,该子句筛选出所有行。

出于这个原因,我认为NOT EXISTS是一个更好的选择:

NOT EXISTS (SELECT 1 FROM BST WHERE BST.P = BST.N) 

你也可以通过添加WHERE P IS NOT NULL两个子查询解决这个问题。

0

声明X IN (A,B)转化为X=A OR X=B。在使用OR时,只有其中一个语句需要为TRUE才能使整个表达式成为TRUE。如果A或B是NULL,那么比较的一部分将等于NULL,但另一部分仍然可以得到结果。

让我们假设B为空,而A实际上等于X.那将是TRUE或NULL,这是TRUE。

声明X NOT (A,B)转换为X<>A AND X<>B。使用AND时,所有的语句都需要为TRUE才能使整个结果为TRUE。如果其中一边是NULL,则整个语句将解析为NULL,而不是TRUE。

如果B为空,并且X不是A,那么您将得到TRUE或NULL,并在最后得到NULL。