2012-03-17 8 views
1

複数のテーブルから同時にデータを取得しようとしています。私の古いシステムでは、クエリを作成し、必要なデータを取得し、次のクエリに使用します。私が参加すると、それらを組み合わせたので、私は、複数のクエリを作る避けたかった:なぜこのJOINは非効率ですか?

SELECT `to`.`id` , `to`.`group`, `to`.`email`, `pTo`.`min_offer`, COUNT(`offerRes`.`id`), `settingsRes`.`email` 
           FROM `members` AS `to` 

           LEFT JOIN (
            SELECT `id` , `min_offer` 
            FROM `profile` 
           ) pTo ON pTo.id = to.id 

           LEFT JOIN (
            SELECT `id`, `from`,`to` 
            FROM `offers` 
           ) offerRes ON offerRes.from = ? && offerRes.to = to.id 

           LEFT JOIN (
            SELECT `id`, `email` 
            FROM `user_settings` 
           ) settingsRes ON settingsRes.id = to.id 

           WHERE to.id = ? LIMIT 1 

私は(to.id)に渡されたIDを使用したプロファイルテーブルや特典のテーブルとユーザ設定テーブルからの結果を得るために、 。これらのテーブルはすべてすべてがマップされるPRIMARY IDを持ちます。私のPHPユーザーは文を準備しましたが、私は? PHPMyAdminでは厳しい値があります。マイEXPLAIN以下のとおりである。私のクエリは、PRIMARYキーidに基づいているとして、それは簡単な検索を行うことができるとき

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 PRIMARY   to  const PRIMARY  PRIMARY 4   const  1 
1 PRIMARY  <derived2> ALL  NULL   NULL NULL NULL  45 
1 PRIMARY  <derived3> ALL  NULL   NULL NULL NULL  1 
1 PRIMARY  <derived4> ALL  NULL   NULL NULL NULL  15 
4 DERIVED  user_settingsALL NULL   NULL NULL NULL  15 
3 DERIVED  offers  system NULL   NULL NULL NULL  1 
2 DERIVED  profile  ALL  NULL   NULL NULL NULL  45 

はなぜMySQLは、プロファイルフィールド内のすべての45行を通過していますか?これをより効率的にする方法はありますか?私が欲しいのは、次の表である:私のクエリは、PRIMARYキーIDに基づいているとして、それは簡単な検索を行うことができるとき

id (from members) - this is optional as this is what is obtained from the user and passed in to SELECT against 
group (from members) - corresponding to the id that is passed in 
email (from members) - corresponding to the id that is passed in 
min_offer (from profile) - also corresponding to the id that is passed in 
NUM_ROWS(from offers) - number of rows corresponding to the id taht is passed in and another number that is also passed in. The offers table has a PRIMARY id but it is a different ID than what is passed in. 
email (from user_settings) - corresponding to the id that is passed in 
+1

INNER以外の結合ほど、クエリの効率が低下します。 –

+0

これらのサブクエリのいずれかが行を返さない場合、内部結合で理解する限り、全体がNULLを返します。これは望ましくない。私はまだ、LEO JOIN ON idCol = someOtherIdColを実行しているときに45レコードすべてを検索しなければならない理由は分かりません。 IDは主キーです。私は間違った説明を読んでいない限り、45行を検索する必要はありませんか? – user974896

+0

左の結合では45行を確認する必要があります。テーブルメンバーのすべての行が結果になりますが、別のテーブルに対応する行がnullフィールドを持つことがわかりません – Jhonathan

答えて

3

はなぜMySQLは、プロファイルフィールド内のすべての45行を通過していますか?

LEFT JOIN `profile` AS pTo ON pTo.id = to.id 

LEFT JOIN `offers` AS offerRes ON offerRes.from = ? && offerRes.to = to.id 

LEFT JOIN `user_settings` AS settingsRes ON settingsRes.id = to.id 
:直接テーブルに参加し、その代わり

LEFT JOIN (
    SELECT `id` , `min_offer` 
    FROM `profile` 
) pTo ON pTo.id = to.id 

-- etc. 

すると、テーブルからすべてのレコードが含まれます結果サブクエリのに参加しているので

+0

Perfect。非常に効率的で、実行されているように動作します。私はJOINを使用する方法を知らなかった。 JOINされたクエリにどのフィールドを指定する必要があると思ったので、後でそれらの変数に "アクセス"できるようになりました(つまり、別のクエリで 'pTo'.min_offerを使うことができます)。今のように私はあなたがこれをやることができるのを見ます、なぜ私は前にしたように誰でもサブクエリを使用しますか?これは、多くのクエリを1つにまとめたものの、効率を維持します。 – user974896

関連する問題