1

多くのテーブルと左結合を含む MySQL の状況があり、問題を解決できません。

私はそれを段階的に単純化しようとします。

私がしようとしている主なタスクは、2 つのテーブルを結合することです。最初のテーブルにはアイテムが含まれ、2 番目のテーブルにはアイテムに対して実行されるアクションが含まれます。items テーブルのすべての行を出力する必要があるため (アクションが実行されていない場合でも)、左結合が解決策のようです:

select item.ID, count(action.ID) as cnt 
from item 
left join action on action.itemID=item.ID 
group by ID

次のステップは、実際に特定の種類のアイテムだけを数える必要があるということです。他の型は必要ないので、where 句でそれらを除外します。

select item.ID, count(action.ID) as cnt 
from item 
left join action on action.itemID=item.ID 
where item.type=3 
group by ID

ここで、事態はもう少し複雑になります。また、別のテーブル (info) を使用して一部の項目を除外する必要があります。そこでは、どうすればいいのかわかりませんでした。しかし、単純な結合と where 句でそれができました。

select item.ID, count(action.ID) as cnt 
from (item, info) 
left join action on action.itemID=item.ID 
where item.type=3 and info.itemID=itemID and info.fr is not null 
group by ID

ここまでは順調ですね。私のクエリは機能し、パフォーマンスは期待どおりです。ここで、最後に行う必要があるのは、別のテーブル (サブアクション) に基づいていくつかのアクション (カウントしない) を除外することです。これは、物事が本当に遅くなり、私を混乱させる場所です. 私はこれを試しました:

select item.ID, count(action.ID) as cnt 
from (item, info) 
left join (
           action join subaction on subaction.actionID=action.ID and subaction.type=6
          ) on action.itemID=item.ID 
where item.type=3 and info.itemID=itemID and info.fr is not null 
group by ID

この時点で、クエリは突然 1000 倍以上遅くなります。私は明らかに何か間違ったことをしています!

必要なことをほぼ実行する単純なクエリを試しました。唯一の問題は、一致するアクションが必要なアイテムが含まれていないことです。しかし、私もそれらが必要です。

select item.ID, count(action.ID) as cnt 
from item, info, action, subaction 
where item.type=3 and info.itemID=itemID and info.fr is not null and 
      action.itemID=item.ID subaction.actionID=action.ID and subaction.type=6 
group by ID

このような問題を解決する方法について誰か提案がありますか? それを行う標準的な方法はありますか?どうもありがとう !

編集

実際、私が提出した最後のクエリは、私が必要としているもののほとんどです。サブクエリが含まれておらず、非常にパフォーマンスが高く、インデックスを最適に使用し、読みやすいなどです。

select item.ID, count(action.ID) as cnt 
from item, info, action, subaction 
where item.type=3 and info.itemID=itemID and info.fr is not null and 
      action.itemID=item.ID subaction.actionID=action.ID and subaction.type=6 
group by ID

機能しない唯一の小さなことは、count(action.ID) が 0 の場合に item.ID が含まれないことです。

したがって、私の質問は、count(action.ID) が 0 のときに item.IDs も返すように、上記のクエリを少し変更する方法だと思います。それらの余分な item.IDs をカウントとして 0 で含めるだけです。

4

1 に答える 1

1

以下のように結合を試みます (結合する前に最初にフィルタ条件を適用しようとします):

      SELECT item.ID, count(action.ID) as cnt 
      FROM item JOIN info
           ON (item.type=3 AND info.fr is not null AND info.itemID=item.itemID)
           LEFT JOIN action 
           ON (action.itemID=item.ID)
           JOIN subaction 
           ON (subaction.actionID=action.ID and subaction.type=6)  
      GROUP by item.ID;

編集:

      SELECT item.ID, count(action.ID) as cnt 
      FROM item JOIN info
           ON (item.type=3 AND info.fr is not null AND info.itemID=item.itemID)
           LEFT JOIN 
           (select a.* FROM action 
              JOIN subaction 
               ON (subaction.actionID=action.ID and subaction.type=6)) AS act 
           ON (act.itemID=item.ID)
      GROUP by item.ID;
于 2012-10-27T02:55:19.310 に答える