0

このクエリは正しい結果を表示しますが、EXPLAINを実行すると、「依存サブクエリ」としてリストされますが、これは悪いと思われますか?

SELECT Competition.CompetitionID, Competition.CompetitionName,     Competition.CompetitionStartDate  
FROM Competition  
WHERE CompetitionID NOT   
IN (  
SELECT CompetitionID  
FROM PicksPoints  
WHERE UserID =1    
)

クエリを次のように変更してみました。

SELECT Competition.CompetitionID, Competition.CompetitionName,   Competition.CompetitionStartDate  
FROM Competition  
LEFT JOIN PicksPoints ON Competition.CompetitionID = PicksPoints.CompetitionID  
WHERE UserID =1  
and PicksPoints.PicksPointsID is null  

ただし、0行が表示されます。実際に機能する最初のクエリと比較して、上記の何が問題になっていますか?

4

2 に答える 2

1

秒クエリは行を生成できません:それは主張します:

WHERE UserID =1  
and PicksPoints.PicksPointsID is null 

しかし、明確にするために、私は次のように書き直します。

WHERE PicksPoints.UserID =1  
and PicksPoints.PicksPointsID is null 

したがって、一方では、PicksPointsどこUserId = 1に行を要求しているのですが、そもそもその行が存在しないことを期待しています。あなたは失敗を見ることができますか?

外部結合はそれでとてもトリッキーです!通常、たとえば、「外部」テーブルの列を使用してフィルタリングしますCompetition。しかし、あなたはそうしたくありません。左に結合されたテーブルでフィルタリングしたい。次のように書き直してみてください。

SELECT Competition.CompetitionID, Competition.CompetitionName,   Competition.CompetitionStartDate  
FROM Competition  
LEFT JOIN PicksPoints ON (Competition.CompetitionID = PicksPoints.CompetitionID AND UserID = 1)
WHERE 
PicksPoints.PicksPointsID is null  

これについての詳細は、この素敵な投稿を読んでください。

ただし、補足として、パフォーマンスの観点から、サブクエリまたは左結合のいずれかを使用すると、問題が発生します。

サブクエリでは、5.6まで(いくつかの良い作業が行われている)、MySQLは内部クエリの最適化に非常に苦手であり、サブクエリは複数回実行されることが予想されるため、問題が発生します。

左から右への結合の順序を指示するので、LEFT JOINあなたは困っています。LEFT JOINただし、フィルタリングは正しいテーブルにあります。つまり、条件をフィルタリングするためにインデックスを使用することはできませんUSerID = 1(または、結合のインデックスを失うことになります)。

于 2012-07-21T04:48:54.973 に答える
0

これらは2つの異なるクエリです。PicksPoints最初のクエリは、(テーブルを介して)ユーザーID 1に関連付けられた競合を検索し、2番目のクエリは、さらにnullを持つユーザーID1PicksPointsID関連付けられた行と結合します。

と呼ばれるテーブルに対して結合していて、結合結果でnullPicksPointsを持つ行を探しているため、2番目のクエリは空になります。PicksPointsIDこれは、次の場合にのみ発生する可能性があります

  1. 2番目のテーブルには、nullPickPointsID 、最初のテーブルの競合IDと一致する競合IDの行がありました。
  2. 最初のテーブルには2番目のテーブルには表示されなかった競合IDがあるため、結合に対する2番目のテーブルの寄与のすべての列はnullです。

PicksPointsID本当に主キーのように聞こえるので、表示されているのはケース2です。したがって、からのすべての列PickPointsIDはnullであり、where句(UserID=1 and PicksPoints.PicksPointsID is null)は常にfalseになり、結果は空になります。

単純な左結合が機能するはずです

select c.CompetitionID, c.CompetitionName, c.CompetitionStartDate  
from Competition c
left join PicksPoints p
on (c.CompetitionID = p.CompetitionID)
where p.UserID <> 1

ファイナルwhereand(複雑な結合句を作成する)に置き換えることも機能する可能性があります。各クエリの計画を分析するのはあなたに任せます。:)

私は個人的にis nullテストの必要性を確信していません。Shlomi Noachによってリンクされた記事は素晴らしく、これを支援するためのヒントがそこにあるかもしれません。

于 2012-07-21T04:20:43.730 に答える