2012-02-20 76 views
20

我的表设置是这样的:检查是否一个项目没有在另一个表中存在

table name: process 
fields: name, id_string 

table name: value_seach 
fields: id_string, value 

我想构建一个select语句,将显示所有的进程名(与它的相应的ID_STRING)在value_search中没有条目。

进程表中的id_string可以是null,并且仍然有一个名称,但如果可能的话,则需要排除这些名称。 value_search中的id_string永远不会是null

我该如何做?

+0

您需要的关系运算符是半差分a.k.a.反连接。 – onedaywhen 2012-02-21 09:09:35

回答

33

一般来说,如果你想不另一个表中存在的行,然后LEFT JOIN其他表和WHERE .. 。对第二个表中的列是NULL。你也提到过你不需要process.id_string为NULL的行。

SELECT p.name, p.id_string 
FROM 
    process p 
    LEFT JOIN value_search v 
     ON v.id_string = p.id_string 
WHERE 
    v.id_string IS NULL 
    AND p.id_string IS NOT NULL 

这被称为反连接。

+0

这是非常有帮助的。谢谢。 – 1man 2018-02-14 19:37:51

2
SELECT 
    name, 
    id_string 
FROM process 
WHERE id_string IS NOT NULL AND id_string NOT IN SELECT id_string FROM value_seach 
+0

这将工作,但会比外部联接慢得多。 – 2012-02-20 18:09:56

+0

同意你的答案更好 – alexsuslin 2012-02-20 18:10:46

4

你想要的查询应该看起来像这样。请注意,JOIN将比WHERE子句中的子查询快得多。

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
    AND p.id_string IS NOT NULL 
    AND v.id_string IS NULL 

查询的一个同样有效的变体上面会:

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
WHERE 
    p.id_string IS NOT NULL 
    AND v.id_string IS NULL 
24

我相信在这里使用Not Exists将是您的最佳选择。

SELECT p.name, p.id_string 
FROM process p 
WHERE 
    NOT p.id_string IS NULL AND 
    NOT EXISTS(
      SELECT NULL 
      FROM value_search v 
      WHERE p.id_string = v.id_string) 
+1

这会起作用,但会比外部联接慢得多。 – 2012-02-20 18:09:34

+4

@BrianDriscoll没有它不会,即使左表具有空值,带有空值检查和不存在的'左外部连接'也会创建相同的查询计划。有关更多信息,请参阅:http://explainextended.com/2009/09/17/not-in-vs-not-exists-vs-left-join-is-null-oracle/。我的值保证是'not null','Left join','Not exists'和'Not in'将会创建相同的查询计划。 – Magnus 2012-02-20 18:14:11

+4

@BrianDriscoll另请注意,对于许多其他DBMS,如SQL服务器,由于无法识别ANTI JOIN,因此带有NULL检查的'Left Outer Join'会产生最差的性能。 – Magnus 2012-02-20 18:39:56

相关问题