📃Пусть у нас есть таблица с клиентами (client_id, name) и заказами (order_id, amount, client_id).
Нужно вывести имя клиента и сумму всех его заказов. Если нет заказов - то 0.
🌷Подход №1 - join (все очень просто)
SELECT name, SUM(COALESCE(amount, 0)) AS total
FROM clients c
LEFT JOIN orders o
ON c.id = o.client_id
GROUP BY name
ORDER BY name
🌷Подход №2 - union
Когда что-то нужно посчитать
🟢группируем отдельно по датасетам
🟢проставляем null в отсутствующих колонках
🟢юнионим
🟢группируем по ключу, если бы мы джойнили
🟢навешиваем нужные функции сверху
WITH grouped AS (
SELECT
client_id AS id,
null AS name,
SUM(amount) AS total
FROM orders
GROUP BY client_id
),
final AS (
SELECT id, name, null AS total FROM clients
UNION
SELECT id, null AS name, total FROM grouped
)
SELECT
MAX(name) AS name,
COALESCE(MAX(total), 0) AS total
FROM final
GROUP BY id
ORDER BY name
На этапе final у нас будет примерно такое:
id name amount
1 Alice null
2 Bob null
3 Cathy null
1 null 2000
2 null 5000
✏️ На моем крошечном датасете в плане запросов в постгре косты второго запроса меньше в 2 раза.
В первом почти все ресурсы тратятся на Hash Join.
#sql_tips