Посмотрим на решение задания про сотрудников, которые продали меньше, чем среднестатистический сотрудник.
В запросе
WITH employee_result AS (
SELECT p.employee_id,
sum (pi.price * pi.count) AS sum_purchases
FROM purchase p,
purchase_item pi
WHERE pi.purchase_id = p.purchase_id
AND p.employee_id IS NOT NULL
GROUP BY p.employee_id
)
SELECT er.employee_id,
e.last_name,
e.first_name,
er.sum_purchases
FROM employee_result er,
employee e
WHERE e.employee_id = er.employee_id
AND er.sum_purchases < (SELECT avg (ern.sum_purchases)
FROM employee_result ern)
ORDER BY er.sum_purchases,
er.employee_id
мы ссылаемся на таблицу employee_result дважды: во фразе FROM и в подзапросе
(SELECT avg (ern.sum_purchases)
FROM employee_result ern)
Это очень удобно. Один раз написал и используешь сколько нужно.
Несколько подзапросов
Пойдем дальше в анализе продаж сотрудниками. Добавим в результат сумму продаж по каждому магазину.
WITH employee_result AS (
SELECT p.employee_id,
p.store_id,
sum (pi.price * pi.count) AS sum_purchases
FROM purchase p,
purchase_item pi
WHERE pi.purchase_id = p.purchase_id
AND p.employee_id IS NOT NULL
GROUP BY p.employee_id,
p.store_id
),
store_result AS (
SELECT er.store_id,
sum (er.sum_purchases) AS sum_purchases
FROM employee_result er
GROUP BY er.store_id
)
SELECT s.name AS store_name,
e.last_name,
e.first_name,
er.sum_purchases AS sum_purchases_employee,
sr.sum_purchases AS sum_purchases_store
FROM employee_result er,
store_result sr,
employee e,
store s
WHERE sr.store_id = er.store_id
AND e.employee_id = er.employee_id
AND s.store_id = er.store_id
ORDER BY s.name,
er.sum_purchases
| # | store_name | last_name | first_name | sum_purchases_employee | sum_purchases_store |
|---|---|---|---|---|---|
| 1 | Big | Громов | Юлиан | 1321800000.00 | 1321800000.00 |
| 2 | Umi | Агафьев | Мирон | 158800.00 | 411300.00 |
| 3 | Umi | Белозёров | Зиновий | 252500.00 | 411300.00 |
| 4 | Адалин-family | Суханов | Влас | 4900.00 | 4900.00 |
| 5 | Март | Картман | Эрик | 47000.00 | 847800.00 |
| 6 | Март | Миронова | Зарина | 800800.00 | 847800.00 |
| 7 | Пионер | Блинова | Любовь | 52200.00 | 52200.00 |
| 8 | Сатурн | Корсаков | Петр | 121500.00 | 121500.00 |
После подзапроса employee_result в WITH появился еще один подзапрос
store_result AS (
SELECT er.store_id,
sum (er.sum_purchases) AS sum_purchases
FROM employee_result er
GROUP BY er.store_id
)
Стоит отметить, что в WITH:
- Можно писать несколько подзапросов.
- Использовать выше определенные подзапросы вместо таблиц.
В основном запросе
SELECT s.name AS store_name,
e.last_name,
e.first_name,
er.sum_purchases AS sum_purchases_employee,
sr.sum_purchases AS sum_purchases_store
FROM employee_result er,
store_result sr,
employee e,
store s
WHERE sr.store_id = er.store_id
AND e.employee_id = er.employee_id
AND s.store_id = er.store_id
ORDER BY s.name,
er.sum_purchases
Используется и employee_result, и store_result.
Разработка запроса
С использованием WITH очень удобно разрабатывать запрос с несколькими подзапросами.
Например, в запросе
WITH employee_result AS (
SELECT p.employee_id,
p.store_id,
sum (pi.price * pi.count) AS sum_purchases
FROM purchase p,
purchase_item pi
WHERE pi.purchase_id = p.purchase_id
AND p.employee_id IS NOT NULL
GROUP BY p.employee_id,
p.store_id
),
store_result AS (
SELECT er.store_id,
sum (er.sum_purchases) AS sum_purchases
FROM employee_result er
GROUP BY er.store_id
)
SELECT s.name AS store_name,
e.last_name,
e.first_name,
er.sum_purchases AS sum_purchases_employee,
sr.sum_purchases AS sum_purchases_store
FROM employee_result er,
store_result sr,
employee e,
store s
WHERE sr.store_id = er.store_id
AND e.employee_id = er.employee_id
AND s.store_id = er.store_id
ORDER BY s.name,
er.sum_purchases
посмотрим, что возвращает каждый подзапрос. Для этого комментируем (или удаляем, мы для краткости удалим) основной запрос и оставляем SELECT * из интересующего подзапроса.
Посморим, что в employee_result:
WITH employee_result AS (
SELECT p.employee_id,
p.store_id,
sum (pi.price * pi.count) AS sum_purchases
FROM purchase p,
purchase_item pi
WHERE pi.purchase_id = p.purchase_id
AND p.employee_id IS NOT NULL
GROUP BY p.employee_id,
p.store_id
),
store_result AS (
SELECT er.store_id,
sum (er.sum_purchases) AS sum_purchases
FROM employee_result er
GROUP BY er.store_id
)
SELECT *
FROM employee_result
| # | employee_id | store_id | sum_purchases |
|---|---|---|---|
| 1 | 25 | 100 | 52200.00 |
| 2 | 8 | 201 | 121500.00 |
| 3 | 43 | 301 | 4900.00 |
| 4 | 29 | 500 | 800800.00 |
| 5 | 15 | 500 | 47000.00 |
| ... | ... | ... | ... |
Что в store_result:
WITH employee_result AS (
SELECT p.employee_id,
p.store_id,
sum (pi.price * pi.count) AS sum_purchases
FROM purchase p,
purchase_item pi
WHERE pi.purchase_id = p.purchase_id
AND p.employee_id IS NOT NULL
GROUP BY p.employee_id,
p.store_id
),
store_result AS (
SELECT er.store_id,
sum (er.sum_purchases) AS sum_purchases
FROM employee_result er
GROUP BY er.store_id
)
SELECT *
FROM store_result
| # | store_id | sum_purchases |
|---|---|---|
| 1 | 100 | 52200.00 |
| 2 | 201 | 121500.00 |
| 3 | 301 | 4900.00 |
| 4 | 500 | 847800.00 |
| ... | ... | ... |