【问题标题】:Oracle: Check if rows exist in other tableOracle:检查其他表中是否存在行
【发布时间】:2010-12-27 09:19:22
【问题描述】:

我有一个查询连接了几个表并返回了很多列。

另一个表的索引列引用其中一个连接表的 PK。现在我想在查询中添加另一列,说明新表中是否存在至少一个具有该 ID 的行。

如果我有一张旧桌子

ID
 1
 2
 3

还有新表

REF_ID
1
1
1
3

那我想得到

ID   REF_EXISTS
 1            1
 2            0
 3            1

我可以想到几种方法来做到这一点,但最优雅/最有效的方法是什么?


编辑 我测试了旧表中提供 50.000 条记录的查询的性能,每隔一条记录匹配新表中的两行,因此一半的记录具有 REF_EXISTS=1。

如果有人感兴趣,我会将平均结果作为 cmets 添加到答案中。谢谢大家!

【问题讨论】:

    标签: sql database oracle join exists


    【解决方案1】:

    另一种选择:

    select O.ID
        , case when N.ref_id is not null then 1 else 0 end as ref_exists
    from old_table o
    left outer join (select distinct ref_id from new_table) N
       on O.id = N.ref_id
    

    【讨论】:

    • +1,因为您在此查询中以 7 分钟的优势击败了我。在将集合外部加入到 old_table 之前,这很好地将 ref_id 分组。我会使用 nvl2(n.ref_id,1,0) 而不是你的案例表达式。
    • 这个查询最快,平均测试时间0.06s。而且不需要 GROUP BY :)
    【解决方案2】:

    我愿意:

    select distinct ID,
           case when exists (select 1 from REF_TABLE where ID_TABLE.ID = REF_TABLE.REF_ID)
        then 1 else 0 end
        from ID_TABLE
    

    如果您在 PK 和 FK 上有索引,您就可以通过表扫描和索引查找来摆脱困境。

    问候 克

    【讨论】:

      【解决方案3】:

      用途:

         SELECT DISTINCT t1.id,
                CASE WHEN t2.ref_id IS NULL THEN 0 ELSE 1 END AS REF_EXISTS
           FROM TABLE_1 t1
      LEFT JOIN TABLE_2 t2 ON t2.ref_id = t1.id
      

      添加了DISTINCT 以确保只显示唯一的行。

      【讨论】:

      • 谢谢,更新版本在我的测试中用了大约 0.17 秒。
      【解决方案4】:

      join 可以为一个 id 返回多行,就像示例数据中的 id=1 一样。您可以通过以下方式将其限制为每个 id 一行:

      SELECT 
          t1.id
      ,   COUNT(DISTINCT t2.ref_id) as REF_EXISTS
      FROM TABLE_1 t1
      LEFT JOIN TABLE_2 t2 ON t2.ref_id = t1.id
      GROUP BY t1.id
      

      group by 确保每个 ID 只有一行。如果找到一行,count(distinct t2.ref_id) 将为 1,否则为 0。

      编辑:你可以在没有group by 的情况下重写它,但我怀疑这会让事情变得更容易:

      SELECT 
          t1.id
      ,   CASE WHEN EXISTS (
              SELECT * FROM TABLE_2 t2 WHERE t2.ref_id = t1.id)
              THEN 1 ELSE 0 END as REF_EXISTS
      ,   ....
      FROM TABLE_1 t1
      

      【讨论】:

      • 是的,这行得通。但我很想避免分组,因为我要选择另外 30 列...还有其他想法吗?
      • 我的经验是使用第一个以获得最佳效率。如果您在 t2.ref_id 上有一个索引,oracle 应该非常聪明地使用它。请务必根据您的选择使用 EXPLAIN PLAN。
      • 你是对的,第一个在我的测试中效率更高(0.20s)。它没有使用 t2.ref_id 上的索引,提供使用它的提示会导致相同的性能(但执行计划不同)。第二个查询是唯一需要在 t2.ref_id (0.25s) 上建立索引的查询,当索引不存在时大约需要 3 分钟 :)
      猜你喜欢
      • 2021-11-11
      • 1970-01-01
      • 2017-10-28
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2015-11-16
      相关资源
      最近更新 更多