Підзапит повертає таблицю
І нарешті третій варіант – коли підзапит повертає цілу таблицю. Це найпоширеніший варіант.
Дуже часто виникають ситуації, коли хочемо трохи підправити певну таблицю. І лише потім об'єднати (за допомогою оператора JOIN ON) виправлену таблицю з іншого.
Давай спочатку візьме найпростіший випадок, де ми об'єднували дві таблиці за допомогою JOIN:
SELECT * FROM employee e JOIN task t ON e.id = t.emploee_id
І як ти, напевно, пам'ятаєш, у таблиці task є завдання, які ні на кого не призначені: employee_id і NULL .
Давай згенеруємо виправлену таблицю , де всі задачі, що повисли, призначимо на директора (його ID = 4).
Для цього скористаємося функцією IFNULL() :
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline FROM task
І результат такого запиту:
id | employee_id | name | deadline |
---|---|---|---|
1 | 1 | Виправити багу на фронтенді | 2022-06-01 |
2 | 2 | Виправити багу на бекенді | 2022-06-15 |
3 | 5 | Купити каву | 2022-07-01 |
4 | 5 | Купити каву | 2022-08-01 |
5 | 5 | Купити каву | 2022-09-01 |
6 | 4 | Прибрати офіс | (NULL) |
7 | 4 | Насолоджуватися життям | (NULL) |
8 | 6 | Насолоджуватися життям | (NULL) |
Червоним кольором відзначений виправлений осередок.
Тепер давай підставимо нашу виправлену таблицю на запит:
SELECT * FROM employee e JOIN task t ON e.id = t.emploee_id
Замість таблиці task .
Виглядати такий запит буде приблизно так:
SELECT * FROM employee e JOIN (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline
FROM task
) t ON e.id = t.emploee_id
Ми замість слова task написали круглі дужки та в них помістабо тіло запиту.
До речі, псевдонім t (аліас) для вкладеного запиту дуже став у нагоді. У вкладеного запиту на відміну від таблиці свого імені немає, тому псевдонім дуже навіть до місця.
І ось результат такого запиту:
id | name | occupation | salary | age | join_date | id | employee_id | name |
---|---|---|---|---|---|---|---|---|
1 | Іванов Іван | Програміст | 100000 | 25 | 2012-06-30 | 1 | 1 | Виправити багу на фронтенді |
2 | Петроов Петроо | Програміст | 80000 | 23 | 2013-08-12 | 2 | 2 | Виправити багу на бекенді |
4 | Рабінович Мойша | Директор | 200000 | 35 | 2015-05-12 | 6 | 4 | Прибрати офіс |
4 | Рабінович Мойша | Директор | 200000 | 35 | 2015-05-12 | 7 | 4 | Насолоджуватися життям |
5 | Кирієнко Анастасія | Офіс менеджер | 40000 | 25 | 2015-10-10 | 4 | 5 | Купити каву |
5 | Кирієнко Анастасія | Офіс менеджер | 40000 | 25 | 2015-10-10 | 5 | 5 | Купити каву |
5 | Кирієнко Анастасія | Офіс менеджер | 40000 | 25 | 2015-10-10 | 3 | 5 | Купити каву |
6 | Васько | Кіт | 1000 | 3 | 2018-11-11 | 8 | 6 | Насолоджуватися життям |
На нашому директорі висить завдання "прибрати офіс", думаю, він швидко знайде, кому її делегувати :) Використання оператора WITH
До речі, починаючи з 8-ї версії MySQL ти більше не зобов'язаний засовувати всі свої запити прямо всередину фінального запиту. Їх можна виконувати окремо. Для цього використовується оператор WITH .
Він дозволяє створити віртуальну таблицю (займенований запит) і його вид задається шаблоном:
WITH ім'я AS (запит)
Часто бувають ситуації, коли у вашому підзапиті є колонки без імені, наприклад, такі як COUNT(*), яким ти не призначив унікальне ім'я. На цей випадок оператор WITH має можливість вказати нові імена колонок для підзапиту.
Другий вид задається шаблоном:
WITH ім'я(колонка1, колонка2, …) AS (запит)
Ти можеш використовувати скільки завгодно віртуальних таблиць (займенованих запитів) і посилатись у них один на одного. Загальний вигляд твого запиту матиме приблизно такий формат:
WITH ім'я1 AS (запит1),
ім'я2 AS (запит2),
ім'я3 AS (запит3)
SELECT * FROM ім'я1 JOIN ім'я2 ON …
Тепер давай візьмемо наш страшний запит:
SELECT * FROM employee e JOIN (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline
FROM task
) t ON e.id = t.emploee_id
І перепишемо його з використанням оператора WITH:
WITH task2(id, employee_id, name, deadline)
AS (SELECT id, IFNULL(employee_id, 4), name, deadline FROM task)
SELECT * FROM employee e JOIN task2 t ON e.id = t.emploee_id
Або можна без імен колонок, але тоді доведеться обов'язково вказувати аліас для функції IFNULL():
WITH task2 AS (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline FROM task
)
SELECT * FROM employee e JOIN task2 t ON e.id = t.emploee_id
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ