Напиши SQL запрос для вывода суммы продаж по каждому пользователю, учитывая, что у пользователя может не быть продаж
Что проверяют
Знаете ли вы, что обычное соединение выбросит пользователей без продаж, и что сумма по пустой группе это NULL, а не ноль. Оговорка «у пользователя может не быть продаж» стоит в вопросе не случайно, это и есть проверяемое место.
Как отвечать
SELECT u.id,
u.name,
COALESCE(sum(s.amount), 0) AS total
FROM users u
LEFT JOIN sales s ON s.user_id = u.id
GROUP BY u.id, u.name
ORDER BY total DESC;Разберите по частям: LEFT JOIN сохраняет всех пользователей, у тех, кто ничего не продал, правая часть заполняется NULL, sum по одним только NULL возвращает NULL, и COALESCE превращает его в ноль. Альтернатива без соединения это скалярный подзапрос или LATERAL с уже посчитанной суммой, что иногда дешевле, когда продаж сильно больше, чем пользователей.
Для Go добавьте два практических довода. COALESCE избавляет от sql.NullInt64 при сканировании, строка читается в обычные поля структуры. И деньги не хранятся в float64: либо целое число копеек, либо numeric в базе с разбором в decimal-тип, иначе округления всплывут в отчётах.
Где спотыкаются
Ставят обычный JOIN. Пользователи без продаж просто исчезают из выдачи, и заметить это на десятке тестовых строк почти невозможно, поэтому ошибка спокойно доезжает до прода.
Убирают COALESCE, считая, что сумма пустого множества равна нулю. В SQL она равна NULL, и дальше это либо ошибка сканирования в Go, либо пустая ячейка в отчёте вместо честного нуля.
Добавляют фильтр по периоду в WHERE, например по дате продажи. Строки с NULL в правой части отсекаются этим же условием, внешнее соединение вырождается во внутреннее, и пользователи без продаж снова пропадают. Такому фильтру место в ON.