1. Вкладені запити в SQL
Мова SQL дозволяє вкладати одні запити до інших запитів. Це дає можливість написати один дуже великий запит, який робитиме щось велике та складне, хоча при цьому читабельність коду значно знижується.
Залежно від того, скільки значень повертають підзапити, змінюється область, де їх можна застосовувати. Загалом можливі три варіанти:
- Підзапит повертає одне єдине значення (одна колонка та один рядок).
- Підзапит повертає список значень (таблиця з однією колонкою).
- Підзапит повертає таблицю (багато колонок, будь-яку кількість рядків).
Давай розберемо один приклад для кожного випадку.
2. Підзапит зі скалярним результатом
Давай знайдемо список усіх наших співробітників з таблиці employee, чия зарплата вища за середню по компанії. Як нам це зробити?
Ми можемо легко відфільтрувати співробітників, порівнявши їхню зарплату із середньою, якщо знатимемо її заздалегідь. У той же час ми вже писали запит, який дає змогу обчислити середню зарплату співробітників компанії. Згадаймо його:
SELECT AVG(salary) FROM employee
MySQL повернув нам значення: 76833.3333.
Як тепер знайти список усіх співробітників, чия зарплата вища за середню? Теж дуже просто:
SELECT * FROM employee
WHERE salary > 76833.3333
Результат цього запиту буде таким:
id | name | occupation | salary |
---|---|---|---|
1 | Шевченко Ігор | Програміст | 100000 |
2 | Коваленко Максим | Програміст | 80000 |
4 | Мельник Степан | Директор | 200000 |
А тепер ми просто поєднаємо обидва запити, підставивши замість значення 76833 перший запит:
SELECT * FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee)
Результат цього запиту буде таким самим:
id | name | occupation | salary |
---|---|---|---|
1 | Шевченко Ігор | Програміст | 100000 |
2 | Коваленко Максим | Програміст | 80000 |
4 | Мельник Степан | Директор | 200000 |
3. Підзапит зі списком значень
Пам'ятаєш, колись давно ми мали завдання — знайти всі записи з однієї таблиці, для яких немає відповідних записів з іншої?
Там ще була така картинка:
Якщо не помиляюся, завдання звучить так: відобразити список усіх співробітників з таблиці employee, для яких немає завдань у таблиці task.
Давай теж знайдемо рішення у два етапи.
Спочатку напишемо запит, який поверне id всіх співробітників, які мають завдання у таблиці task. Тільки не забувай про дві речі:
- прибрати дублікати — використовуй ключове слово DISTINCT.
- забрати значення NULL з результату.
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
І ось ми отримали гарний результат такого запиту:
employee_id |
---|
1 |
2 |
5 |
4 |
6 |
Давай для зручності тимчасово запишемо його у вигляді послідовності: 1,2,5,4,6. Тепер напишемо другий запит — до таблиці employee, яка поверне нам список співробітників, id яких не містяться в першому списку:
SELECT * FROM employee
WHERE id NOT IN (1,2,5,4,6)
І результат такого запиту:
id | name | occupation | salary | age | join_date |
---|---|---|---|---|---|
3 | Шевченко Данило | Тестувальник | 40000 | 30 | 2014-01-01 |
А тепер можна, як і в попередньому прикладі, поєднати обидва запити, підставивши замість списку ID тіло першого запиту.
SELECT * FROM employee
WHERE id NOT IN (
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
)