Вложени заявки в SQL

Езикът SQL ви позволява да влагате една заявка в друга заявка. Това прави възможно да се напише една много голяма заявка, която ще направи нещо голямо и сложно, въпреки че четимостта на codeа е значително намалена.

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

  • Подзаявката връща една единствена стойност (една колона и един ред).
  • Подзаявката връща списък със стойности (table с една колона).
  • Подзаявката връща table (много колони, произволен брой редове).

Нека разгледаме по един пример за всеки случай.

Подзаявка със скаларен резултат

Нека намерим списък на всички наши служители от tableта на служителите, чиято заплата е по-висока от средната за компанията. Как можем да го направим?

Можем лесно да филтрираме служителите, като сравняваме тяхната заплата със средната, ако я знаем предварително. В същото време вече сме написали заявка, която ни позволява да изчислим средната заплата на служителите на компанията. Да си го припомним:

SELECT AVG(salary) FROM employee 

Тогава MySQL ни върна стойността: 76833.3333 .

Как сега да намерите списък на всички служители, чиято заплата е над средната? Освен това е много просто:

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

Резултатът от тази заявка ще бъде:

document за самоличност име професия заплата
1 Ivanов Ivan Програмист 100 000
2 Peterов Петър Програмист 80 000
4 Рабинович Мойша Директор 200 000

И сега просто комбинираме двете заявки, като заместваме първата заявка instead of стойността 76833:

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

Резултатът от тази заявка ще бъде същият:

document за самоличност име професия заплата
1 Ivanов Ivan Програмист 100 000
2 Peterов Петър Програмист 80 000
4 Рабинович Мойша Директор 200 000

Подзаявка със списък от стойности

Спомняте ли си едно време имахме задача - да намерим всички записи от една table, за които няма съответстващи записи от друга?

Имаше и тази снимка:

Ако не се лъжа, задачата е следната: показване на списък с всички служители от tableта на служителите, за които няма задачи в tableта със задачи .

Нека също намерим решение в две стъпки.

Първо, нека напишем заявка, която ще върне идентификатора на всички служители, които имат задачи в tableта със задачи. Само запомнете две неща:

  • премахнете дубликати - използвайте ключовата дума DISTINCT.
  • премахнете NULL стойности от резултата.
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

И тук получихме красив резултат от такава заявка:

ИД на служител
1
2
5
4
6

Нека временно го запишем за удобство като последователност: 1,2,5,4,6. Сега нека напишем втора заявка - към tableта на служителите, която ще върне списък със служители, чийто идентификатор не се съдържа в първия списък:

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

И резултатът от тази заявка:

document за самоличност име професия заплата възраст дата на присъединяване
3 Ivanов Сергей Тестер 40 000 тридесет 2014-01-01

И сега, Howто в предишния пример, можете да комбинирате и двете заявки, като просто замените тялото на първата заявка instead of списъка с идентификатори.

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )