内部连接选择(A,B)A和B vs其中(A,B)在mysql的select(A,B)中

时间:2013-10-29 09:56:37

标签: mysql sql

这两者之间最好的查询是什么? 他们输出相同的结果,期望一个人在where in内进行调整,另一个在inner join内。

select uv.* from version v inner join user_version uv ON v.id=uv.version_id
WHERE (v.number, v.master_id) IN (
select max(v.number) as number, v.master_id 
  from version v inner join user_version uv ON v.id=uv.version_id group by v.master_id);

 select * from user_version uv 
   inner join version v on v.id=uv.version_id and v.number
   inner join (
      select uv2.user_id, max(v2.number) maxNumber, v2.master_id master_id, v2.id version_id from version v2 
         inner join user_version uv2 on v2.id=uv2.version_id group by v2.master_id ) test
   on test.master_id=v.master_id and test.maxNumber=v.number ;

我创建了一个带有示例的sqlfiddle:http://sqlfiddle.com/#!2/76001/62 (这个想法是获得链接到给定用户的“主”实体的最大版本)

如果你有其他想法(我正在使用mysql,所以我不能使用windows函数)

由于

1 个答案:

答案 0 :(得分:3)

回答这个问题并不容易。您应该知道一件重要的事情:MySQL将IN (<static values list>)IN (<subquery>)视为different queries。第一个等于范围比较(如.. OR = .. OR =),而第二个等于= ANY () - 并且它不相同。所以,简而言之:在子查询中使用IN会导致查询ANY(),即使子查询是独立的并且返回静态值列表,MySQL也不会使用索引。悲伤,但是真的。 MySQL无法预测,即使很明显,也不会使用索引。如果您将使用JOIN(即重写您的IN (<subquery>)) - 那么MySQL将使用JOIN条件的索引,如果可能的话。

现在,使用分区时,第二种情况可能是JOININ。如果您将使用JOIN - 那么,遗憾的是 - 但MySQL在常见情况下也无法预测JOIN的分区 - 并且它将使用整套分区。将JOIN替换为IN (<static list>)将更改EXPLAIN PARTITION图片:MySQL将仅使用在IN子句中指定的范围内选择值所需的分区。但是,再次,这不适用于IN (<subquery>)

作为一个结论 - 当我们谈到MySQL如何处理IN子查询时,很遗憾 - 在一般情况下,它不能安全地替换为JOIN(这是关于分区的情况) 。因此,常见的解决方案是:将子查询与应用程序级别的主查询分开。如果我们说的是独立子查询,返回静态值列表,这是最好的建议 - 那么你可以将该值列表替换为IN(<static list>)并获得好处:MySQL将使用索引,如果我们说的话关于分区,只会使用实际需要的分区。

相关问题