あなたの質問に答えるために、いいえ。c.id
としてエイリアスされたインラインビュー内を参照することはできませんx
。エラーが発生するはずです。
ただし、これを削除すると、セミデカルト積のために、とのエイリアスが付けられたインラインビュー間で、クエリが膨らんだカウントを返す可能性がx
ありc
ます。
そのため、述語を再配置する必要があり、c2.idをから返す必要がありますx
(つまり、述語をSELECTリストに追加すると、GROUP BYで既に参照されています)。
これはクエリと同等ですが、コンマ結合演算子を置き換え、結合述語をON句に再配置するように書き直しただけです。このステートメントはあなたのステートメントと同等であり、無効です):
SELECT t.id
, SUM(x.count_s)
FROM ( SELECT count(*) AS count_s
FROM course c2
JOIN student s
ON c2.id = s.course_id
AND c2.id = c.id -- INVALID here
GROUP
BY c2.id
) x
CROSS -- no join predicate
JOIN course c
JOIN teacher t
ON t.id = c.teacher_id
これを修正するには、c2.idをのSELECTリストに追加し、x
その述語を再配置します。このようなもの:
SELECT t.id
, SUM(x.count_s)
FROM ( SELECT count(*) AS count_s
, c2.id -- added
FROM course c2
JOIN student s
ON c2.id = s.course_id
-- AND c2.id = c.id -- relocated (removed from here)
GROUP
BY c2.id
) x
JOIN course c
ON x.id = c.id -- relocated (added here)
JOIN teacher t
ON t.id = c.teacher_id
id
それがUNIQUEであり、NOT NULLであると仮定するとcourse
、そのクエリは妥当なカウントを返します(ただし、ゼロのカウントは「欠落」します)。
「ゼロ」カウントを返すには、OUTER結合を使用する必要があります。そして、私は常にLEFT JOINを使用することを好むので、最も外側のクエリのテーブル/インラインビューを並べ替える必要があります。
SELECT t.id
, IFNULL(SUM(x.count_s),0)
FROM teacher t
LEFT
JOIN course c
ON c.teacher_id = t.id
LEFT
JOIN ( SELECT count(*) AS count_s
, c2.id -- added
FROM course c2
JOIN student s
ON c2.id = s.course_id
-- AND c2.id = c.id -- relocated (removed from here)
GROUP
BY c2.id
) x
ON x.id = c.id -- relocated (added here)
id
それが各テーブルのPRIMARYKEY(または同等のUNIQUEおよびNOT NULL)であると仮定すると、「正しい」カウントが返されます。
course
としてエイリアスされたインラインビューにテーブルを含める必要はありませんx
。GROUPBYs.course_idで十分です。
SELECT t.id
, IFNULL(SUM(x.count_s),0)
FROM teacher t
LEFT
JOIN course c
ON c.teacher_id = t.id
LEFT
JOIN ( SELECT count(*) AS count_s
, s.course_id
FROM student s
GROUP
BY s.course_id
) x
ON x.course_id = c.id -- relocated (added here)
そのクエリは有効な「カウント」を返します。
単純なステートメントの方が理解しやすいでしょう。カウントを取得する方法は次のとおりです。
SELECT t.id AS teacher_id
, COUNT(s.id) AS how_many_students_taught
FROM teacher t
LEFT
JOIN course c
ON c.id = t.course_id
LEFT
JOIN student s
ON s.course_id = c.id
GROUP
BY t.id