Oracle 使用IN、JOIN或EXISTS子句

Oracle 使用IN、JOIN或EXISTS子句,oracle,Oracle,我有一个使用IN子句编写的查询。我觉得如果有很多记录,使用IN子句可能会影响性能 我尝试使用JOIN和EXISTS子句编写使用IN子句编写的相同查询。然而,它并没有发挥作用,也没有产生预期的效果 下面是使用IN子句编写的查询片段 SELECT * FROM TABLE1 WHERE id IN (SELECT id FROM TABLE2 WHERE my_date IN (Select max(my_date) from TABLE2)) ORDER BY id; 我使用EXISTS子句尝试

我有一个使用IN子句编写的查询。我觉得如果有很多记录,使用IN子句可能会影响性能

我尝试使用JOIN和EXISTS子句编写使用IN子句编写的相同查询。然而,它并没有发挥作用,也没有产生预期的效果

下面是使用IN子句编写的查询片段

SELECT * FROM TABLE1 WHERE id IN (SELECT id FROM TABLE2 WHERE my_date IN (Select max(my_date) from TABLE2)) ORDER BY id;
我使用EXISTS子句尝试了以下查询,但它不起作用:

Select * from TABLE1 t1 where exists
(
Select 1 from TABLE2 t2 
where exists 
(
Select max(my_date) from TABLE2 t3
where t2.my_date = t3.my_date)
where t1.id = t2.id) order by t1.id;
有人能建议如何使用EXISTS和join来实现结果吗

注意:上面示例中引用的my_date是DateTimeTimestamp字段。

您的in子句查询非常完美

 SELECT * FROM TABLE1
  WHERE id IN
   (
    SELECT id FROM TABLE2
    WHERE my_date = (Select max(my_date) from TABLE2)
   ) 
 ORDER BY id;
如果你想要一个存在的

如果表1中的每个id在表2中只有一个id,您可以选择加入, 因为EXISTS和IN将禁止重复ID

 SELECT * FROM TABLE1 T1
 INNER JOIN ( 
               SELECT id FROM TABLE2
               WHERE my_date = (Select max(my_date) from TABLE2)
            ) T2
    ON (T1.id = T2.id)
 ORDER BY id;

很抱歉,我无法在mo测试这一点,但是,关于:

select * 
  from table1 t1
  where exists (
    select *
      from table2 t2
      where t1.id = t2.id 
        and t2.my_date = (select max(my_date) from table2 t3)
)
另请参见Oracle中与中存在的差异的详细信息。您可以从这里开始:

您是否认为存在性能影响,或者您是否观察到性能影响


任何最近的Oracle优化器都应该能够很好地处理您的IN查询。检查您的解释计划,看看是否有任何东西触发了像全表扫描这样的昂贵操作。这是重写查询或可能向表中添加索引的起点。

不要仅仅因为您觉得查询可能会受到影响而重写已经正常工作且运行良好的查询。测量和测试

如果您运行的是现代Oracle 10.2或更高版本,那么您应该使用简单的经验法则

将“IN”与“EXISTS”视为性能上的等价物,Oracle本身就是这样做的 为场景编写最清晰、正确的查询 使数据库统计信息保持最新 分析执行计划 以前的文章,甚至是2003年的Tom threads,讨论了Oracle 7、8或9,以及IN是如何变慢的,或者EXISTS为每个和所有其他旧的基于规则的优化器产生的缺点都过时了。Tom Kyte承认这一点,并在稍后就此主题撰写了几篇文章,但不幸的是,他的旧Ask Tom档案对甲骨文的声誉或甲骨文的整体能力造成了一些损害


IN==存在。Oracle的optimizer将在这两者之间进行转换,并在过去五年中我测试过的大多数场景中选择类似的计划。

使用您建议的连接方法,我将获得重复的记录。我想我需要使用distinct。如果我使用EXISTS子句,我需要使用with吗?我不想创建任何临时表。是的,我提到过重复的表太多,无法加入。存在我使用CTE来确保,我们只查询表一次。否则它可能会以嵌套循环结束,这可能会影响性能。您所指的临时表已使用CTE.WITH子句完成
select * 
  from table1 t1
  where exists (
    select *
      from table2 t2
      where t1.id = t2.id 
        and t2.my_date = (select max(my_date) from table2 t3)
)