Условие
База Northwind (классика учебных SQL-задач). Напишите запросы:
- Полную информацию о первом пункте в заказе
10248(таблицаOrderDetails). - Количество сотрудников, которые работали
1996-07-04. - Количество заказов, обработанных каждым сотрудником
1996-07-04. - Все заказы клиента
«Ana Trujillo Emparedados y helados»— номера заказов с итоговой стоимостью. - Среднюю стоимость заказа этого же клиента.
- Количество купленных продуктов и общую стоимость заказов на каждую дату.
- Количество отправленных заказов каждой компанией-грузоотправителем.
- Количество купленных единиц каждого продукта (по убыванию).
- Список клиентов, у которых сумма всех заказов ≥ 5000.
Решение
Подход
Northwind — классика; основные таблицы: Orders, OrderDetails, Customers, Employees, Products, Shippers. Задачи проверяют умение делать JOIN, агрегировать, фильтровать.
Реализация
-- 1. Первый пункт в заказе 10248
SELECT *
FROM OrderDetails
WHERE OrderID = 10248
ORDER BY ProductID
LIMIT 1;«Первый» условен — по ProductID, по позиции? Уточнили бы, в задаче — ORDER BY ProductID LIMIT 1.
-- 2. Сколько сотрудников работали 1996-07-04
SELECT COUNT(DISTINCT EmployeeID) AS employees_active
FROM Orders
WHERE OrderDate = '1996-07-04';«Работал» = принял хотя бы один заказ. Если нужно по табелю — другая таблица; в Northwind её нет.
-- 3. Количество заказов на сотрудника 1996-07-04
SELECT EmployeeID, COUNT(*) AS orders_count
FROM Orders
WHERE OrderDate = '1996-07-04'
GROUP BY EmployeeID
ORDER BY orders_count DESC;-- 4. Заказы Ana Trujillo с итоговой стоимостью
SELECT
o.OrderID,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS order_total
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID
JOIN OrderDetails od ON od.OrderID = o.OrderID
WHERE c.CompanyName = 'Ana Trujillo Emparedados y helados'
GROUP BY o.OrderID
ORDER BY o.OrderID;-- 5. Средняя стоимость заказа того же клиента
WITH order_totals AS (
SELECT
o.OrderID,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS total
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID
JOIN OrderDetails od ON od.OrderID = o.OrderID
WHERE c.CompanyName = 'Ana Trujillo Emparedados y helados'
GROUP BY o.OrderID
)
SELECT AVG(total) AS avg_order_total
FROM order_totals;-- 6. Количество продуктов и стоимость заказов на каждую дату
SELECT
o.OrderDate,
SUM(od.Quantity) AS products_qty,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS revenue
FROM Orders o
JOIN OrderDetails od ON od.OrderID = o.OrderID
GROUP BY o.OrderDate
ORDER BY o.OrderDate;-- 7. Заказы по компании-грузоотправителю
SELECT
s.CompanyName,
COUNT(o.OrderID) AS shipped_orders
FROM Shippers s
LEFT JOIN Orders o
ON o.ShipVia = s.ShipperID
AND o.ShippedDate IS NOT NULL
GROUP BY s.CompanyName
ORDER BY shipped_orders DESC;LEFT JOIN — чтобы показать нулевые шипперы. ShippedDate IS NOT NULL — фильтр «реально отправленных».
-- 8. Купленные единицы по продуктам
SELECT
p.ProductName,
SUM(od.Quantity) AS units_sold
FROM Products p
JOIN OrderDetails od ON od.ProductID = p.ProductID
GROUP BY p.ProductName
ORDER BY units_sold DESC;-- 9. Клиенты с суммой заказов ≥ 5000
SELECT
c.CompanyName,
SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) AS total_spent
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID
JOIN OrderDetails od ON od.OrderID = o.OrderID
GROUP BY c.CompanyName
HAVING SUM(od.UnitPrice * od.Quantity * (1 - od.Discount)) >= 5000
ORDER BY total_spent DESC;Анализ результата
- Расчёт стоимости — везде одна формула:
UnitPrice * Quantity * (1 - Discount). В NorthwindDiscount— float от 0 до 1. HAVINGvsWHERE.HAVINGпосле агрегации;WHERE— до. Фильтр наSUMидёт вHAVING.
Подводные камни
- Discount ≠ 0. Без
(1 - Discount)стоимость завышена. - «Первый пункт». В реляционной модели нет порядка строк. Уточните «по чему сортировать»: ProductID, время добавления (нет в Northwind).
- «Сотрудник работал». В Northwind «работал» можно определить только через
Orders.EmployeeID— это часть, а не весь рабочий день. На реальном HR-собесе нужны учётные таблицы. - Один заказ → много строк. В
OrderDetailsкаждая строка — позиция. Не считайтеCOUNT(*)для «числа заказов» — нужноCOUNT(DISTINCT OrderID). - Тип даты. Если
OrderDate—DATETIME, фильтр= '1996-07-04'может пропустить часть строк. ИспользуйтеDATE(OrderDate) = '1996-07-04'или>= '1996-07-04' AND < '1996-07-05'. - NULL в ShippedDate. Это «не отправлено» — фильтруйте, если задача про отправленные.
Эталонный ответ
Список 9 запросов, ключевая формула стоимости — UnitPrice * Quantity * (1 - Discount). Сравнения в HAVING, агрегации в GROUP BY, отдельная аккуратность с OrderDate (тип) и Discount (часто забывают).