Собесов

МТС: набор SQL-запросов на базе Northwind

SQLБазовый SQL и агрегацииЛёгкаяMiddle

Условие

База Northwind (классика учебных SQL-задач). Напишите запросы:

  1. Полную информацию о первом пункте в заказе 10248 (таблица OrderDetails).
  2. Количество сотрудников, которые работали 1996-07-04.
  3. Количество заказов, обработанных каждым сотрудником 1996-07-04.
  4. Все заказы клиента «Ana Trujillo Emparedados y helados» — номера заказов с итоговой стоимостью.
  5. Среднюю стоимость заказа этого же клиента.
  6. Количество купленных продуктов и общую стоимость заказов на каждую дату.
  7. Количество отправленных заказов каждой компанией-грузоотправителем.
  8. Количество купленных единиц каждого продукта (по убыванию).
  9. Список клиентов, у которых сумма всех заказов ≥ 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). В Northwind Discount — float от 0 до 1.
  • HAVING vs WHERE. HAVING после агрегации; WHERE — до. Фильтр на SUM идёт в HAVING.

Подводные камни

  1. Discount ≠ 0. Без (1 - Discount) стоимость завышена.
  2. «Первый пункт». В реляционной модели нет порядка строк. Уточните «по чему сортировать»: ProductID, время добавления (нет в Northwind).
  3. «Сотрудник работал». В Northwind «работал» можно определить только через Orders.EmployeeID — это часть, а не весь рабочий день. На реальном HR-собесе нужны учётные таблицы.
  4. Один заказ → много строк. В OrderDetails каждая строка — позиция. Не считайте COUNT(*) для «числа заказов» — нужно COUNT(DISTINCT OrderID).
  5. Тип даты. Если OrderDateDATETIME, фильтр = '1996-07-04' может пропустить часть строк. Используйте DATE(OrderDate) = '1996-07-04' или >= '1996-07-04' AND < '1996-07-05'.
  6. NULL в ShippedDate. Это «не отправлено» — фильтруйте, если задача про отправленные.

Эталонный ответ

Список 9 запросов, ключевая формула стоимости — UnitPrice * Quantity * (1 - Discount). Сравнения в HAVING, агрегации в GROUP BY, отдельная аккуратность с OrderDate (тип) и Discount (часто забывают).

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти