检查另一个表中是否存在项目

use*_*153 27 sql oracle anti-join exists

我的表格设置如下:

table name: process
fields: name, id_string

table name: value_seach
fields: id_string, value
Run Code Online (Sandbox Code Playgroud)

我想构造一个select语句,它将显示在value_search中没有条目的所有进程名称(使用它的各自的id_string).

进程表中的id_string可以为null,并且仍然具有名称,但如果可能,则需要排除这些名称.value_search中的id_string永远不能为null

我该怎么做呢?

zgp*_*max 41

通常,如果您想要在另一个表中不存在的行,则LEFT JOIN另一个表和WHERE ... IS 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
Run Code Online (Sandbox Code Playgroud)

这被称为反连接.


Mag*_*nus 27

我相信使用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)
Run Code Online (Sandbox Code Playgroud)

  • @BrianDriscoll不,它不会,`left outer join` with`null` check和`Not Exists`将创建相同的查询计划,即使左表有空值.有关详细信息,请参阅: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`将创建相同的查询计划. (4认同)
  • @BrianDriscoll还要注意,对于许多其他DBMS,例如SQL服务器,使用`NULL`检查的`Left Outer Join`会产生最差的性能,因为它无法识别ANTI JOIN. (4认同)
  • 这是对真实数据进行测试的结果.(PostgreSQL 9.4):1)"左连接":解释:"哈希右连接t1,过滤器t2.id为空,seq扫描t2,哈希t1,Seq扫描t1"; 实际执行时间:11.9秒.2)"不存在的地方":解释:"哈希反连接,t1扫描t1,哈希t2,seq扫描t2".实际执行时间:11.9秒.结论:实际执行时间相同,但第二种方法的查询计划看起来更好. (2认同)

Bri*_*oll 5

您想要的查询应如下所示。请注意,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
Run Code Online (Sandbox Code Playgroud)

上面查询的同等有效变体是:

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
Run Code Online (Sandbox Code Playgroud)