2017-01-30 7 views
0

人物、プロパティ、合計の3つのテーブルを組み合わせて、LEFT JOINを使用しています。私は次のクエリが本当に高速であることがわかりますが、テーブル-2またはテーブル-3に対応するデータがないテーブル-1のすべての行を私に渡すことはできません。基本的には、テーブル2とテーブル3にデータがある行のみが表示されます。SQLで複数のLEFT JOINが遅いです。どのように最適化するのですか?

SELECT a.*, b.propery_address, c.person_asset_total 
FROM persons AS a 
LEFT JOIN properties AS b ON a.id = b.person_id 
LEFT JOIN totals AS c ON a.id = c.person_id 
WHERE a.city = 'New York' AND 
     c.description = 'Total Immovable' 

次の問合せに関係なく、対応するデータまたは表2及び表3からのデータがあるか否かの表1からすべての行を含めることによって、私に正しい結果を与える一方。ただし、このクエリは処理時間が非常に長くかかります。

FROM persons AS a 
LEFT JOIN 
    properties AS b ON a.id = b.person_id 
LEFT JOIN 
    (SELECT person_id, person_asset_total 
    FROM totals 
    WHERE description = 'Total Immovable' 
    ) AS c ON a.id = c.person_id 
WHERE a.city = 'New York' 

2番目のクエリに相当しますが、最初のクエリに相当実行のスピードでデータを与えるクエリを記述するためのより良い方法はありますか?

+0

最初のクエリでは、WHERE句は 'c.description'のNULL値を許可せず、左結合の外側を否定し、内部結合と同等になります。 'c.description = 'Total Immovable''述語を' WHERE'節からLEFT JOINの 'ON'節に再配置してください。 – spencer7593

答えて

4

は、サブクエリを使用しないでください:

SELECT p.*, pr.propery_address, t.person_asset_total 
FROM persons p LEFT JOIN 
    properties pr 
    ON p.id = pr.person_id LEFT JOIN 
    totals t 
    ON a.id = c.person_id AND t.description = 'Total Immovable' 
WHERE p.city = 'New York'; 

あなたのアプローチは、ほぼすべての他のデータベースに罰金だろう。しかし、MySQLは "導出されたテーブル"を実現します。そのため、最適化が非常に難しくなります。上記にも同じ効果があります。

また、表の別名を表名の略語に変更したことに気づくでしょう。これにより、クエリの実行がより簡単になります。

+1

@gordonありがとうございました!クエリは完全に機能します。あなたのプロフィールであなたが言及したあなたの本の内容を読んだ。興味深いいくつかのデータマイニングの概念を把握するように見えます。 –

+1

この素晴らしいソリューションに私の2セントの説明を追加するだけです。OPの最初のクエリで実行されたように、クエリの最後に「Total Immovable」に関するWHERE句を含めて、テーブルが結合された後に制限を適用します。したがって、JOINが左結合であっても、一致しない行はすべて削除されます。 Gordonの応答は、テーブルが結合される前にWHERE句を適用します。 – watermelon

関連する問題