SQL查询:如何将IN()转换为JOIN?

时间:2010-04-06 14:17:45

标签: sql mysql oracle db2 performance

我有很多这样的SQL查询:

SELECT o.Id, o.attrib1, o.attrib2 
  FROM table1 o 
WHERE o.Id IN (
                SELECT DISTINCT Id 
                  FROM table1
                     , table2
                     , table3 
                 WHERE ...
               )

这些查询必须在不同的数据库引擎(MySql,Oracle,DB2,MS-Sql,Hypersonic)上运行,因此我只能使用常见的SQL语法。

Here我读过,使用MySql时IN语句未经优化且速度非常慢,所以我想将其切换为JOIN

我试过了:

SELECT o.Id, o.attrib1, o.attrib2 
  FROM table1 o, table2, table3 
  WHERE ...

但这并未考虑DISTINCT关键字。

问题:如何使用JOIN方法摆脱重复的行?

4 个答案:

答案 0 :(得分:4)

要使用JOIN编写此内容,您可以使用内部选择并加入:

SELECT o.Id, o.attrib1, o.attrib2 FROM table1 o
JOIN (
  SELECT DISTINCT Id FROM table1, table2, table3 WHERE ...
) T1
ON o.id = T1.Id

我不确定这会更快,但也许......你可以亲自试试。

通常,仅将自己限制为可在多个数据库上运行的SQL不会产生最佳性能。

答案 1 :(得分:2)

  

但这没有考虑到   DISTINCT关键字。

您不需要子查询中的distinctin将返回外部查询中的一行,无论它是否匹配子查询中的一行或一百行。因此,如果您想提高查询的性能,那么distinct将是一个良好的开端。

调整in子句的一种方法是使用exists重写它们。根据数据的分布,这可能会更高效,或者可能更慢。通过调整,基准是王道。

SELECT o.Id, o.attrib1, o.attrib2 
FROM table1 o 
WHERE EXISTS (
  SELECT  Id FROM table1 t1, table2 t2, table3 t3 WHERE ... 
  AND  ( t1.id = o.id 
         or t2.id = o.id 
         or t3.id = o.id 
)

不了解您的业务逻辑,额外过滤器的精确配置可能是错误的。

顺便提一下,我注意到外部查询和子查询都有table1。如果这不是将您的实际SQL转录到此处的错误,您可能需要考虑这是否有意义。最好避免两次查询该表;使用exists make可以更轻松地避免双击。

答案 2 :(得分:0)

SELECT DISTINCT o.Id, o.attrib1, o.attrib2 
  FROM table1 o, table2, table3 
 WHERE ...

虽然如果您需要支持许多不同的数据库后端,您可能希望在数据层中为每个数据库后端提供一组自己的存储库类,这样您就可以针对每个数据库优化查询。这也使您能够持久存储在其他类型的数据库,xml或Web服务中,或者在需要的任何时候出现。

答案 3 :(得分:0)

我不确定你真的明白你的问题是什么。你为什么不试试这个:

SELECT distinct o.Id, o.attrib1, o.attrib2
FROM
table1 o
, table o1
, table o2
...
where
o1.id1 =  o.id
or o2.id = o.id