Написать SQL-запрос для расчёта общей суммы продаж по каждому продавцу

68. Посчитать общую сумму продаж по каждому продавцу

Условие задачи:
Даны таблицы Salespersons, Customers и Orders.

Необходимо написать SQL-запрос, который:

  • выводит идентификаторы всех продавцов;

  • считает общую сумму заказов клиентов каждого продавца;

  • включает продавцов, у которых нет клиентов или заказов;

  • для продавцов без заказов возвращает сумму 0;

  • сортирует результат по id продавца.

Код:

CREATE TABLE Salespersons (
    id SERIAL PRIMARY KEY,
    name VARCHAR(20)
);

CREATE TABLE Customers (
    id SERIAL PRIMARY KEY,
    salesperson_id INT
);

CREATE TABLE Orders (
    id SERIAL PRIMARY KEY,
    customer_id INT,
    price INT
);

TRUNCATE Orders;

INSERT INTO Orders (customer_id, price)
VALUES
    (8, 2480),
    (6, 654),
    (13, 2938),
    (4, 2071),
    (4, 2412),
    (1, 236),
    (17, 2514),
    (18, 849),
    (7, 925),
    (10, 93),
    (14, 449),
    (15, 923),
    (14, 160),
    (1, 1978),
    (14, 2903),
    (13, 2093),
    (14, 2429),
    (12, 1058),
    (18, 2342),
    (19, 484),
    (4, 1040),
    (14, 2346),
    (19, 239),
    (14, 2253),
    (20, 510),
    (12, 497),
    (6, 1638),
    (9, 1088),
    (6, 1766),
    (2, 1548);

INSERT INTO Salespersons (name)
VALUES
    ('Stephanie'),
    ('Rebecca'),
    ('Deborah'),
    ('Jordan'),
    ('Veronica'),
    ('Marisa'),
    ('Deanna'),
    ('Emma'),
    ('Julie'),
    ('Maria');

INSERT INTO Customers (salesperson_id)
VALUES
    (5),
    (4),
    (8),
    (10),
    (3),
    (1),
    (6),
    (2),
    (1),
    (4),
    (4),
    (5),
    (8),
    (8),
    (10),
    (5),
    (3),
    (1),
    (6),
    (3);

Спойлеры к решению

Подсказки
💡 Начинай запрос с Salespersons, чтобы сохранить всех продавцов.
💡 Соедини продавцов с клиентами, а клиентов — с заказами.
💡 Используй LEFT JOIN, чтобы не потерять продавцов без клиентов или заказов.
💡 Общую сумму посчитай через SUM(o.price).
💡 Для продавцов без заказов SUM() вернёт NULL, поэтому используй COALESCE().

Решение
SELECT
    s.id AS salesperson_id,
    COALESCE(SUM(o.price), 0) AS total_sales
FROM Salespersons s
LEFT JOIN Customers c
    ON c.salesperson_id = s.id
LEFT JOIN Orders o
    ON o.customer_id = c.id
GROUP BY s.id
ORDER BY s.id;

Сначала продавцы соединяются со своими клиентами:

LEFT JOIN Customers c
    ON c.salesperson_id = s.id

Затем клиенты соединяются со своими заказами:

LEFT JOIN Orders o
    ON o.customer_id = c.id

LEFT JOIN нужен на обоих этапах, чтобы в результате остались даже продавцы, у которых нет клиентов или у клиентов нет заказов.

Общая сумма продаж рассчитывается через:

SUM(o.price)

Для продавца без заказов SUM() вернёт NULL, поэтому:

COALESCE(SUM(o.price), 0)

заменяет его на 0.

После группировки по продавцу:

GROUP BY s.id

каждая строка результата соответствует одному продавцу, а:

ORDER BY s.id

сортирует результат по его идентификатору.