Няколко важни точки относно използването на 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, както в решението на Charles Bretana. Но предполагам, че може да искате заявката да включва някои други колони от 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
клауза.