连接与相关的存在子查询

时间:2010-12-16 03:13:58

标签: sql correlated-subquery

在Derby和/或MySQL中,我想知道:

的表现
select c0.documentid from contentblob as c0 where c0.documentid > ? 
  and c0.blobid = ? 
  and exists (select * from contentblob c1 where c1.documentid = c0.documentid 
              and c1.blobid = ?)
  order by c0.documentid

请注意,将为两个blobid比较提供不同的值。这个查询的作用是返回表中出现的id(至少)两次:一次使用blobid1,一次使用blobid2。

与等效的自我加入相比,

当然,假设contentblob表的documentid和blobid列上有索引。

如果不清楚,这里的相关模式是一个包含两个varchar列的表,documentid和blobid。它们被组成以形成主键。

如果没有任何东西可以查询db中的查询分析器,我会去那么做。

2 个答案:

答案 0 :(得分:2)

通常,相关子查询比连接更昂贵,甚至是外部自连接,但在这种情况下,您只需要一个常规的内部自连接:

SELECT c0.documentid
  FROM contentblob AS c0
  JOIN contentblob AS c1 ON c1.documentid = c0.documentid
 WHERE c0.documentid > ? 
   AND c0.blobid = ?
   AND c1.blobid = ?
   AND c0.blobid < c1.blobid
 ORDER BY c0.documentid

最后一个条件避免看到具有相同文档ID和相关blob ID值的一对行的两个条目;没有它,你会看到文档ID两次,一次是c0.blobid = v1,一次是c0.blobid = v2。

您可能希望将c1.blobid条件移动到ON子句中,但优化器应该为您执行此操作。还要检查优化器是否使用了适当的索引。目前还不完全清楚该索引是什么(但我认为一个带有blobid的索引作为前导列可能表现最佳),但是如果表很大并且优化器正在使用表的顺序扫描,那么就会出现问题

答案 1 :(得分:0)

我认为左连接会更清晰

  select c0.documentid from contentblob as c0 where c0.documentid > ? 
  and c0.blobid = ? 
  left join contentblob c1 on c0.documentid = c1.documentid 
       and c1.blobid = ? 
  order by c0.documentid

里程因不同的数据库引擎而异,并且也会因表格大小,索引基数等而有所不同,但我的直觉是联接会表现得更好。