我无法理解的连接聚合行为

Ste*_*wie 5 mysql query

查询 1:

 SELECT c.class_id,
       SUM
       (
        CASE
         WHEN s.student_id IS NULL THEN 0
         ELSE 1
        END
       ) as total_students 
  FROM classes c LEFT JOIN students s ON c.class_id = s.class_id
GROUP BY c.class_id;
Run Code Online (Sandbox Code Playgroud)

结果:

453 100
461 10
462 19
464 0
471 0
499 133
Run Code Online (Sandbox Code Playgroud)

伟大的 !

查询2:(添加where条件过滤学生类型)

 SELECT c.class_id,
       SUM
       (
        CASE
         WHEN s.student_id IS NULL THEN 0
         ELSE 1
        END
       ) as total_students 
  FROM classes c LEFT JOIN students s ON c.class_id = s.class_id WHERE s.student_type='instate'
GROUP BY c.class_id;
Run Code Online (Sandbox Code Playgroud)

结果:

453 89
461 5
462 19
499 43
Run Code Online (Sandbox Code Playgroud)

所有的数字都是正确的,除了那些计数为 0 的数字消失了:!

这是为什么 ?

Rol*_*DBA 1

WHERE 子句正在检查s.student_type='instate'

在 LEFT JOIN 中,右侧的所有内容都是 NULL,因此 WHERE 子句不会计算任何内容。

如果可以的话,我想建议稍微重写一下您的查询:

而不是这个

SELECT c.class_id, 
       SUM 
       ( 
        CASE 
         WHEN s.student_id IS NULL THEN 0 
         ELSE 1 
        END 
       ) as total_students  
  FROM classes c LEFT JOIN students s ON c.class_id = s.class_id 
GROUP BY c.class_id; 
Run Code Online (Sandbox Code Playgroud)

像这样写得更紧凑

SELECT c.class_id, SUM(1-ISNULL(s.student_id)) as total_students
FROM classes c LEFT JOIN students s USING (class_id) 
GROUP BY c.class_id; 
Run Code Online (Sandbox Code Playgroud)

现在,如果您想过滤 Student_type 并返回零,则必须像这样重写查询:

SELECT
    A.class_id,
    IFNULL(B.total_students,0) total_students
FROM classes A LEFT JOIN
(
    SELECT c.class_id, COUNT(s.student_id) as total_students
    FROM classes c INNER JOIN students s USING (class_id)
    WHERE s.student_type='instate'
    GROUP BY c.class_id
) B USING (class_id);
Run Code Online (Sandbox Code Playgroud)

更新时间 2012-03-08 13:11 美国东部时间

现在我很好奇

这是您的查询

SELECT class_id,
(
    SELECT count(*) FROM students a
    WHERE a.class_id=e.class_id
    AND a.student_type='instate'
) FROM classes e WHERE class_account='92';
Run Code Online (Sandbox Code Playgroud)

请试试这个

SELECT
    COUNT(DISTINCT e.class_id)
FROM
    (SELECT class_id FROM classes WHERE class_account='92') e
    INNER JOIN
    (SELECT class_id FROM students WHERE student_type='instate') a
    USING (class_id)
;
Run Code Online (Sandbox Code Playgroud)

在运行此新查询之前,请确保您具有以下索引:

ALTER TABLE classes ADD INDEX (class_account,class_id);
ALTER TABLE students ADD INDEX (student_type,class_id);
Run Code Online (Sandbox Code Playgroud)