5

这两者之间最好的查询是什么?它们输出相同的结果,期望一个在 a 内执行条件where in,另一个在 a 内执行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功能)

谢谢

4

1 回答 1

3

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

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

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

于 2013-10-29T10:09:05.693 回答