PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

PostgreSQL - Неуспешна корелирана подзаявка?

Няколко важни точки относно използването на 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;

И така, за да обобщим, заявките се изпълняват от машината на базата данни според поредица от стъпки:

  1. Генериране на набор от редове от таблица(и), включително всички редове, произведени от JOIN .
  2. Оценете WHERE условия срещу набора от редове, филтриране на редове, които не съвпадат.
  3. Изчисляване на изрази в списък за избор за всеки от набора от редове.
  4. Прилагане на псевдоними на колони (имайте предвид, че това е отделна стъпка, което означава, че не можете да използвате псевдоними в изрази в списъка за избор).
  5. Кондензирайте групите до един ред за група според GROUP BY клауза.
  6. Оценете HAVING условия срещу групи, филтриране на групи, които не съвпадат.
  7. Сортиране на резултата според ORDER BY клауза.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rownum в postgresql

  2. ГРЕШКА:нулевата стойност в идентификатора на колона нарушава ограничението за не-нулево

  3. прилагане на АКТУАЛИЗАЦИЯ на SELECT в Postgres

  4. PostgreSQL ОПИСАТЕ ТАБЛИЦА

  5. PostgreSQL 11 - Процедури