5

これら2つの間で最適なクエリは何ですか? where inそれらは同じ結果を出力します。一方が a 内で条件を実行し、もう一方が an 内で条件を実行していることを期待して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

この質問に答えるのは簡単ではありません。重要なことを 1 つ知っておく必要があります。MySQL はIN (<static values list>)IN (<subquery>)異なるクエリとして扱います。最初のものは範囲比較(のように.. OR = .. OR =) に等しく、2 番目は= ANY ()- に等しく、同じではありません。つまり、簡単に言うと、INwith subquery を使用すると query with が発生し、MySQL は subquery が独立していてstatic list of valuesANY()を返す場合でも index を使用しません。悲しいけれど事実です。MySQL はそれを予測できないため、明らかであってもインデックスは使用されません。使用する場合(つまり、 を書き換える場合) 、可能であれば、MySQL は条件にインデックスを使用します。JOININ (<subquery>)JOIN

さて、2番目のケースは、パーティションを使用する場合ですJOIN。残念ながら、IN使用する場合、MySQLは一般的なケースでパーティションを予測することもできず、パーティションのセット全体を使用します。に置き換えると状況が変わります: MySQL は、句内で指定された範囲から値を選択するために必要なパーティションのみを使用します。しかし、繰り返しますが、これは では機能しません。JOINJOINJOININ (<static list>)EXPLAIN PARTITIONININ (<subquery>)

結論として - 残念なことに、MySQL がサブクエリをどのように処理しているかについて話していると、一般的に安全INに置き換えることができません(それはパーティショニングの場合です)。JOINしたがって、一般的な解決策は次のとおりです。アプリケーションレベルでサブクエリをメインクエリから分離します。静的な値のリストを返す独立したサブクエリについて話しているのであれば、それが最良の提案です。その値のリストを as に置き換えて、IN(<static list>)利点を得ることができます。MySQL はそれにインデックスを使用します。それらから必要なものが使用されます。

于 2013-10-29T10:09:05.693 に答える