【问题标题】:Checking whether an item does not exist in another table检查一个项目是否在另一个表中不存在
【发布时间】:2012-03-11 01:58:35
【问题描述】:

我的桌子是这样设置的:

table name: process
fields: name, id_string

table name: value_seach
fields: id_string, value

我想构建一个 select 语句,它将显示在 value_search 中没有条目的所有进程名称(及其各自的 id_string)。

进程表中的id_string可以为null,并且仍然有名字,但是如果可能的话需要排除。 value_search 中的 id_string 永远不能为 null

我该怎么做?

【问题讨论】:

  • 您需要的关系运算符是半差分,也就是反连接。

标签: sql oracle exists anti-join


【解决方案1】:
SELECT 
  name,
  id_string
FROM process
WHERE id_string IS NOT NULL AND id_string NOT IN SELECT id_string FROM value_seach

【讨论】:

    【解决方案2】:

    您想要的查询应该如下所示。请注意,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
    

    【讨论】:

      【解决方案3】:

      一般来说,如果您想要另一个表中不存在的行,那么 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
      

      这称为反连接。

      【讨论】:

      • 这很有帮助。谢谢。
      • 请注意,如果您需要过滤要查找缺少连接的列(即示例中的 v),则需要在 JOIN 子句中执行此操作,而不是 WHERE .这对于有更多 SQL 经验的人来说可能很明显,但这不是我尝试的第一件事,所以我认为它可能会帮助一些人。
      【解决方案4】:

      我相信在这里使用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)
      

      【讨论】:

      • @BrianDriscoll 不,它不会,Left outer joinnull 检查和 Not Exists 将创建相同的查询计划,即使左表是否有空值。请参阅:explainextended.com/2009/09/17/… 了解更多信息。我保证这些值是not nullLeft joinNot existsNot in 将创建相同的查询计划。
      • @BrianDriscoll 另请注意,对于许多其他 DBMS,例如 SQL 服务器,Left Outer JoinNULL 检查会产生最差的性能,因为它无法识别 ANTI JOIN。
      • 如果您想在不存在的 where 子句上检查辅助 ID,该查询也可以使用。
      • 这是对真实数据的测试结果。 (PostgreSQL 9.4):1)“左连接”:解释:“t1上的哈希右连接,过滤器t2.id为空,t2上的序列扫描,哈希t1,序列扫描t1”;实际执行时间:11.9 秒。 2)“哪里不存在”:说明:“Hash Anti Join, Seq Scan on t1, Hash t2, Seq Scan on t2”。实际执行时间:11.9 秒。结论:实际执行时间相同,但第二种方法的查询计划看起来更好。
      猜你喜欢
      • 2013-12-12
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 1970-01-01
      • 2022-08-24
      • 2018-10-23
      • 1970-01-01
      • 2015-10-09
      相关资源
      最近更新 更多