例如,我有几个相关的表。
教师桌
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;
它有效,但是也许我错了或者有更好的方法吗?
答案 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_id
,students.std_tch_id
和lessons.les_tch_id
进行索引都是这些查询的最重要因素