这两者之间最好的查询是什么?
他们输出相同的结果,期望一个人在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函数)
由于
答案 0 :(得分:3)
回答这个问题并不容易。您应该知道一件重要的事情:MySQL将IN (<static values list>)
和IN (<subquery>)
视为different queries。第一个等于范围比较(如.. OR = .. OR =
),而第二个等于= ANY ()
- 并且它不相同。所以,简而言之:在子查询中使用IN
会导致查询ANY()
,即使子查询是独立的并且返回静态值列表,MySQL也不会使用索引。悲伤,但是真的。 MySQL无法预测,即使很明显,也不会使用索引。如果您将使用JOIN
(即重写您的IN (<subquery>)
) - 那么MySQL将使用JOIN
条件的索引,如果可能的话。
现在,使用分区时,第二种情况可能是JOIN
和IN
。如果您将使用JOIN
- 那么,遗憾的是 - 但MySQL在常见情况下也无法预测JOIN
的分区 - 并且它将使用整套分区。将JOIN
替换为IN (<static list>)
将更改EXPLAIN PARTITION
图片:MySQL将仅使用在IN
子句中指定的范围内选择值所需的分区。但是,再次,这不适用于IN (<subquery>)
。
作为一个结论 - 当我们谈到MySQL如何处理IN
子查询时,很遗憾 - 在一般情况下,它不能安全地替换为JOIN
(这是关于分区的情况) 。因此,常见的解决方案是:将子查询与应用程序级别的主查询分开。如果我们说的是独立子查询,返回静态值列表,这是最好的建议 - 那么你可以将该值列表替换为IN(<static list>)
并获得好处:MySQL将使用索引,如果我们说的话关于分区,只会使用实际需要的分区。