Многократный выбор количества () в одном выборе из связанных таблиц - PullRequest
1 голос
/ 21 марта 2019

Для примера у меня есть несколько связанных таблиц.

стол преподавателей

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 голосов
/ 22 марта 2019

Как сказал 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, вероятно, является наиболее важным фактором для этих запросов

0 голосов
/ 21 марта 2019

Ваш запрос выглядит нормально, как есть (я бы просто рекомендовал префикс всех имен полей с псевдонимами таблиц, для лучшей читаемости и удобства сопровождения).

Если вы хотите избежать использования встроенных подзапросов дляПодсчитать общее количество учеников и уроков. Одним из решений будет использование агрегированного JOIN ed запроса с 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

Независимо от того, работает ли он лучше, чем оригиналзапрос действительно зависит от вашей схемы и данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...