以不同的方式编写SQL查询

时间:2015-03-19 14:58:34

标签: mysql sql oracle

我编写了一个查询,用通用表检查表的完整性。查询是以下

SELECT * FROM Universal
WHERE UNIVERSAL.TYPE=MYTYPE
  AND Universal.CLASS=MYCLASS
  AND Universal.ID NOT IN (SELECT Mytable.ID FROM Mytable)

如您所见,我在查找完整性之前过滤了通用表,两者都在同一个查询中。我现在发现当我删除NOT IN部分时,查询运行正常,但是当我包含它时,我得不到任何结果。这个查询有什么问题?如何使用其他形式编写,例如使用连接或其他东西?

4 个答案:

答案 0 :(得分:2)

SELECT * FROM Universal
WHERE UNIVERSAL.TYPE=MYTYPE
  AND Universal.CLASS=MYCLASS
  AND Universal.ID NOT IN (SELECT Mytable.ID FROM Mytable
                           WHERE Mytable.ID IS NOT NULL)

空而不是......!

SELECT返回WHERE子句为TRUE的行,且不返回FALSE行。

也不返回UNKNOWN行(即NULL行。)这通常不是问题,但是当涉及到NOT IN时,许多程序员会感到惊讶。

假设您有一张汽车牌桌,并且您想要返回列表(或子查询)中找不到的颜色的汽车:

select * from cars where color not in ('red', 'blue')

很容易理解,所有车辆都会返回红色和蓝色。

但是如果颜色列表使用未知颜色(NULL)进行扩展,那么它将是:

select * from cars where color not in ('red', 'blue', NULL)

现在WHERE子句不知道是否例如黄色车是否在列表中,肯定不是红色或蓝色,但我们无法判断它是不是那种未知的NULL颜色...... I.e。 WHERE子句变为未知,并且不返回任何行!

这里程序员可以通过在子查询中指定IS NOT NULL来避免使用未知颜色。 (或者转换为NOT EXISTS,这是“空安全”。)

答案 1 :(得分:2)

所以你想要选择不在Mytable中的Universal的所有内容吗? 使用LEFT JOIN将选择来自和Unive的所有内容,并且只选择Mytable中与Universal相匹配的行。因此,如果Mytable.ID为null,那么Universal的那一行在Mytable中没有匹配的行:

SELECT * FROM Universal
LEFT JOIN Universal.ID = Mytable.ID
WHERE UNIVERSAL.TYPE=MYTYPE
  AND Universal.CLASS=MYCLASS
  AND Mytable.ID IS NULL;

答案 2 :(得分:2)

我使用您的架构和查询创建了一个SQL小提琴。它运行正常。 Demo 1

但是当我向Mytable添加NULL值时,它不再起作用。这是一个例子: Demo 2

如果您采用该示例并从Mytable中过滤掉空值,则可以再次正常工作。 Demo 3

答案 3 :(得分:0)

SELECT * FROM Universal U
WHERE U.TYPE=MYTYPE
AND U.CLASS=MYCLASS
AND NOT EXISTS (SELECT ID FROM Mytable WHERE ID = U.ID)