2017-06-22 130 views
1

我有一个简单的多学校管理系统,我正在努力获得教师总数以及特定学校的学生总数。我的表结构如下:MYSQL加入三张表

 teachers 
-------------------------- 
id | schoolid | Name | etc... 
-------------------------- 
1 | 1  | Bob | 
2 | 1  | Sarah| 
3 | 2  | John | 


     students 
-------------------------- 
id | schoolid | Name | etc... 
-------------------------- 
1 | 1  | Jack | 
2 | 1  | David| 
3 | 2  | Adam | 

     schools 
-------------------------- 
id |  Name  | etc... 
--------------------------- 
1 | River Park High | 
2 | Stirling High | 

我可以指望刚刚全部用下面的查询教师:

SELECT COUNT(a.id) AS `totalteachers` 
FROM teachers a 
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1' 

,同样我可以用下面的查询次数,教师数量:

SELECT COUNT(a.id) AS `totalstudents` 
FROM students a 
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1' 

但是,我试图结合这两个查询来得到这样一个简单的结果:

totalstudents | totalteachers 
-------------------------------- 
     2  |  2 

我曾尝试以下:

SELECT COUNT(a.id) as `totalteachers`, COUNT(c.id) as `totalstudents` 
FROM teachers a 
LEFT JOIN schools b ON a.schoolid = b.id 
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5' 

回答

2

多个左连接的问题是它为每个学生生成每个老师的附加记录;人为地夸大你的计数

有四种方式来解决这个问题:(IMO最好什么是安德鲁骨所做的那样)

只需选择直列没有连接,因此该计数不膨胀。 (最希望在我的脑海里,因为它很容易维护)

SELECT (SELECT COUNT(a.id) AS `totalteachers` 
     FROM teachers a 
     WHERE A.SchoolID = '1') as TotalTeachers 
    , (SELECT COUNT(a.id) AS `totalstudents` 
     FROM students a 
     WHERE a.SchoolID = '1') as TotalStudents 

使用子查询,首先得到计数加入之前,然后再加入。由于count总是1,因此交叉连接可以工作。

SELECT totalTeachers, totalStudents 
FROM (SELECT COUNT(a.id) AS `totalteachers` 
     FROM teachers a 
     LEFT JOIN schools b 
     ON a.schoolid = b.id 
     WHERE b.id = '1') 
CROSS JOIN (SELECT COUNT(a.id) AS `totalstudents` 
      FROM students a 
      LEFT JOIN schools b ON a.schoolid = b.id 
      WHERE b.id = '1') 

使用关键字的计数范围内不同以免重复计数和否定人工通货膨胀(至少希望在我的脑海,因为这隐藏了人工计数增加)

SELECT COUNT(distinct a.id) as `totalteachers`, COUNT(distinct c.id) as `totalstudents` 
FROM teachers a 
LEFT JOIN schools b ON a.schoolid = b.id 
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5' 

另一种方式要使用窗口函数,但是这些在mySQL中不可用。

+0

这是我正面临的确切问题,人为夸大计数!我选择了你的第三个解决方案(使用不同的),它的功能就像一个魅力!感谢您抽出宝贵时间回答我的问题,并帮助我理解:)我很感激。 – Bruno

0
SELECT COUNT(t.id) AS TotalTeachers, COUNT(st.id) AS TotalStudents 
FROM schools s 
INNER JOIN teachers t 
ON s.id = t.schoolid 
INNER JOIN students st 
ON s.id = st.schoolid 

试试这个SQL。我没有尝试,但它应该工作。

3

你可以做这样的事情

SELECT 
    id, name, s.total AS totalstudents, t.total AS totalteachers 
FROM schools 
    JOIN (SELECT schoolid, COUNT(id) AS total FROM teachers GROUP BY schoolid) 
    AS t ON t.schoolid = id   
    JOIN (SELECT schoolid, COUNT(id) AS total FROM students GROUP BY schoolid) 
    AS s ON s.schoolid = id 

那么你可以添加where id = 2或任何限制的学校。

+0

感谢您的回答安德鲁,我欣赏它:) – Bruno

+0

很好的答案。这使得学生可以轻松地设置where子句。 – xQbert