相关表中的一个选择中的多个选择count()

时间:2019-03-21 19:18:53

标签: mysql sql

例如,我有几个相关的表。

教师桌

tch_id
tch_name

学生桌

std_id
std_name
std_tch_id

课程表

les_id
les_std_id
les_tch_id

我尝试选择:

select 
    tch_name,
    (select count(std_id) from students where std_tch_id = tch_id) as TotalStd,
    (select count(les_id) from lessons where les_tch_id = tch_id) as TotalLes
from teachers 
order by tch_id;

它有效,但是也许我错了或者有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

您的查询看起来不错(我建议您为所有字段名称添加表别名,以提高可读性和可维护性。

如果您希望避免使用内联子查询来计算学生和课程总数,则一种解决方案是使用聚合的JOIN查询和COUNT(DISTINCT ...)来计算计数,而无需重复项:

SELECT t.tch_name, COUNT(DISTINCT s.std_id) TotalStd, COUNT(DISTINCT l.les_id) TotalLes
FROM teachers t
LEFT JOIN students s ON s.std_tch_id = t.tch_id
LEFT JOIN lessons  l ON l.les_tch_id = t.tch_id
GROUP BY t.tch_id, t.tch_name
ORDER BY t.tch_id

这是否比原始查询要好,实际上取决于您的架构和数据。

答案 1 :(得分:0)

就像gmb所说的,您的查询没有什么特别的错误;但是,与大多数查询一样,有些替代方案具有不同的性能特征。照原样,我在下面提供的服务可能会达到或优于您的服务。您的子查询是相关的,这意味着可能会对外部查询的每个结果重新执行它们;这将只执行一次子查询,然后使用索引进行相对较快的联接。

SELECT t.tch_name, tsc.sCount as TotalStd, tlc.lCount as TotalLes
FROM teachers AS t
LEFT JOIN (
   SELECT std_tch_id AS tch_id, COUNT(std_id) AS sCount 
   FROM students 
   GROUP BY std_tch_id
) AS tsc ON t.tch_id = tsc.tch_id
LEFT JOIN (
   SELECT les_tch_id AS tch_id, COUNT(les_id) AS lCount 
   FROM lessons 
   GROUP BY les_tch_id
) AS tlc ON t.tch_id = tlc.tch_id
ORDER BY t.tch_id;

但是,如果最终查询有些不同,则您的查询可能会更好。例如,如果每个表都有一百万行,但是外部查询具有WHERE条件,可以将其从teacher表中迅速缩小到十几行,然后执行子查询(计算一个一个老师)比一次执行我的老师(计算另外两个表中所有老师的计数)便宜很多。

在任何一种情况下,确保对teachers.tch_idstudents.std_tch_idlessons.les_tch_id进行索引都是这些查询的最重要因素