Несколько важных моментов об использовании SQL:
- Вы не можете использовать псевдонимы столбцов в предложении WHERE, но вы можете использовать в предложении HAVING. Это причина ошибки, которую вы получили.
- Вы можете лучше считать, используя JOIN и GROUP BY, чем используя коррелированные подзапросы. Это будет намного быстрее.
- Используйте предложение HAVING для фильтрации групп.
Вот как бы я написал этот запрос:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
Я понимаю, что этот запрос может пропустить JOIN
с t1, как в решении Чарльза Бретаны. Но я предполагаю, что вы могли бы захотеть, чтобы запрос включал некоторые другие столбцы из t1.
Re: вопрос в комментарии:
Разница в том, что предложение WHERE
оценивается по строкам, прежде чем GROUP BY
сводит группы к одной строке на группу. Предложение HAVING
оценивается после формирования групп. Таким образом, вы не можете, например, изменить COUNT()
группы с помощью HAVING
; Вы можете исключить только саму группу.
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;
В приведенном выше запросе WHERE
фильтрует строки, соответствующие условию, и HAVING
фильтрует группы, количество которых не менее пяти.
Смысл, который вызывает у большинства людей путаницу, заключается в том, что у них нет предложения GROUP BY
, поэтому кажется подобно HAVING
и WHERE
взаимозаменяемы.
WHERE
вычисляется перед выражениями в списке выбора. Это может быть неочевидно, потому что синтаксис SQL ставит список выбора на первое место. Таким образом, вы можете сэкономить много дорогостоящих вычислений, используя WHERE
для ограничения строк.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
Если вы используете запрос, подобный приведенному выше, выражения в списке выбора вычисляются для каждой строки , только чтобы отбросить большинство результатов из-за условия HAVING
. Однако приведенный ниже запрос вычисляет выражение только для отдельной строки , соответствующей условию WHERE
.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Итак, подведем итог: запросы выполняются ядром базы данных в соответствии с последовательностью шагов:
- Создание набора строк из таблицы (таблиц), включая любые строки, созданные с помощью
JOIN
.
- Оцените
WHERE
условия по набору строк, отфильтровывая строки, которые не совпадают.
- Вычислить выражения в списке выбора для каждого в наборе строк.
- Применение псевдонимов столбцов (обратите внимание, что это отдельный шаг, что означает, что вы не можете использовать псевдонимы в выражениях в списке выбора).
- Сжатие групп в одну строку для каждой группы согласно пункту
GROUP BY
.
- Оцените
HAVING
условий по группам, отфильтровывая группы, которые не соответствуют.
- Сортировать результат в соответствии с предложением
ORDER BY
.