Към съдържанието
wannacode

Редът на изпълнение на заявката

Накратко: Заявката се пише от SELECT, но базата я изпълнява в ред FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY и LIMIT.

Проблем

Тук работи, там не

В урока за групите ORDER BY month ползваше псевдонима от SELECT. В урока за HAVING повтаряхме целия SUM(...), а SUM в WHERE даде грешка. Защо псевдонимът става на едно място, а на друго не?

Отговорът е в реда, в който базата чете заявката. Той не е редът, в който я пишеш.

Идеята

Пише се в един ред, изпълнява се в друг

Пишеш така:

SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT

Базата мисли така:

  1. FROM: откъде са редовете;
  2. WHERE: кои редове остават;
  3. GROUP BY: групите;
  4. HAVING: кои групи остават;
  5. SELECT: какво се показва и как се казва;
  6. ORDER BY: подреждането;
  7. LIMIT: колко реда.

Това е логическият ред на изпълнение на заявката. Трите най-натоварени месеца, без отказаните поръчки:

SQLбаза: магазин

Стъпка по стъпка: FROM взима 60-те поръчки. WHERE маха 7-те отказани и остават 53. GROUP BY ги разделя на 14 месеца. HAVING оставя шестте с поне 5 поръчки. SELECT смята месеца и броя и им дава имена. ORDER BY ги подрежда, а LIMIT взима първите три.

По-точно, за любопитните

Това е редът, в който заявката трябва да изглежда, че се изпълнява. Истинският план може да е друг: базата може да ползва индекс или да прескочи стъпка, стига резултатът да е същият. Плана на заявката ще видим в модула за индексите.

Идеята

Защо псевдонимът става в ORDER BY

Псевдонимът се ражда в SELECT, на стъпка 5. ORDER BY е на стъпка 6, затова името вече го има:

SQLбаза: магазин

Трите най-големи поръчки. Това работи във всяка база. В WHERE, GROUP BY и HAVING по правило псевдонимът още го няма, защото са преди SELECT.

Пробвай

Най-активните клиенти

Покажи петимата клиенти с най-много поръчки: customer_id и броя в колона orders, най-много пръв. При равен брой по-малкият customer_id е пръв.

SQLбаза: магазин

Виж го

Какво прощава SQLite

По правилото псевдоним в WHERE не би трябвало да става. Продуктите, които с 20% отстъпка струват под 1 €:

SQLбаза: магазин

SQLite го приема. Приема псевдоним и в GROUP BY:

SQLбаза: магазин

Другите бази не са толкова отстъпчиви. PostgreSQL приема псевдоним в GROUP BY, но не и в WHERE: там казва, че колона sale няма. SQL Server не го приема нито в WHERE, нито в GROUP BY.

Отстъпчивостта на SQLite има граници. Ако псевдонимът е същият като име на колона, WHERE взима колоната:

SQLбаза: магазин

Излизат два продукта, а не четири: WHERE price < 1 гледа истинската цена, а не цената с отстъпка. А псевдоним на обобщение в WHERE пак е „misuse of aggregate“, защото групи на стъпка 2 още няма:

SQLбаза: магазин

Заявка, която ще работи навсякъде: в WHERE повтаряй израза (WHERE price * 0.8 < 1), а псевдонимите ползвай свободно в ORDER BY.

Упражнение

Месечният отчет

Собственичката иска отчет за 2026 г.: за всеки месец колко поръчки има (без отказаните) и от колко различни клиенти. Месеците с по-малко от 3 поръчки са твърде тихи и не ѝ трябват.

Покажи колоните month (година-месец), orders и customers за месеците на 2026 г. с поне 3 поръчки без отказаните, по ред на месеците.

SQLбаза: магазин

Тест

Провери се

1. С коя част започва базата, когато изпълнява заявката?
2. Защо ORDER BY total работи, когато total е псевдоним от SELECT?
3. Кое е вярно за WHERE sale < 1, когато sale е псевдоним от SELECT?
4. Заявката има ORDER BY orders DESC и LIMIT 3. Кога се взимат трите реда?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·