要回答你的问题,不。您不能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 in 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
是每个表上的 PRIMARY KEY(或等效的 UNIQUE 和 NOT NULL),那么这将返回“正确”计数。
不必将course
表格包含在别名为x
. GROUP BY s.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