← К оглавлению занятия

Занятие 27. Практикум 7

📁 Блок: SQL / MySQL / Подзапросы и CTE ⏱️ Время изучения: ~90 мин 🎯 Сложность: Практикум
#join #where #null #in #select #as #create

⚡ Кратко: домашнее задание

  • Продукты без заказов — LEFT JOIN, подзапрос, CTE.
  • Средняя выручка по сотрудникам через CTE.
  • Клиенты с заказами дороже среднего.

🏠 Домашнее задание

Все задания выполняются в базе northwind. Постарайтесь решить каждую задачу как минимум двумя способами.

Задание 1. Продукты без заказов

Найдите продукты, которые ни разу не попадали в order_details. Решите задачу тремя способами:

  • с помощью LEFT JOIN;
  • с помощью подзапроса и NOT IN;
  • с помощью CTE.

Решение через LEFT JOIN

USE northwind;

SELECT p.id, p.product_name
FROM products AS p
LEFT JOIN order_details AS od ON p.id = od.product_id
WHERE od.product_id IS NULL;

Решение через подзапрос

USE northwind;

SELECT id, product_name
FROM products
WHERE id NOT IN (
    SELECT DISTINCT product_id FROM order_details
);

Примечание: в продакшене NOT EXISTS часто предпочтительнее NOT IN, потому что корректно обрабатывает NULL.

Решение через CTE

USE northwind;

WITH ordered_products AS (
    SELECT DISTINCT product_id FROM order_details
)
SELECT id, product_name
FROM products
WHERE id NOT IN (SELECT product_id FROM ordered_products);

Задание 2. Средняя выручка по сотрудникам

Для каждого сотрудника вычислите среднюю выручку с одного заказа. Используйте CTE для подготовки промежуточных сумм по заказам.

USE northwind;

WITH order_revenue AS (
    SELECT o.id AS order_id,
           o.employee_id,
           SUM(od.unit_price * od.quantity) AS revenue
    FROM orders AS o
    JOIN order_details AS od ON o.id = od.order_id
    GROUP BY o.id, o.employee_id
)
SELECT e.first_name, e.last_name, AVG(orv.revenue) AS avg_order_revenue
FROM employees AS e
JOIN order_revenue AS orv ON e.id = orv.employee_id
GROUP BY e.id, e.first_name, e.last_name;

Задание 3. Клиенты с заказами дороже среднего

Найдите клиентов, у которых есть хотя бы один заказ, общая сумма которого превышает среднюю сумму заказа по всей базе. Используйте CTE.

USE northwind;

WITH order_totals AS (
    SELECT o.id AS order_id,
           o.customer_id,
           SUM(od.unit_price * od.quantity) AS total
    FROM orders AS o
    JOIN order_details AS od ON o.id = od.order_id
    GROUP BY o.id, o.customer_id
),
avg_order AS (
    SELECT AVG(total) AS avg_total FROM order_totals
)
SELECT DISTINCT c.first_name, c.last_name
FROM customers AS c
JOIN order_totals AS ot ON c.id = ot.customer_id
WHERE ot.total > (SELECT avg_total FROM avg_order);
Проверить по документации: точные имена столбцов в схеме northwind могут отличаться. Адаптируйте запросы под реальные названия таблиц и полей.