
Ключи и JOIN: связать операции со счетами и категориями
Нормализуем модель бюджета и соединяем таблицы по ключам. Учимся выбирать INNER и LEFT JOIN, замечать размножение строк и не связывать данные по похожему тексту.
Зачем это нужно
Если в каждой операции хранить слова Продукты и Карта, опечатка создаст новую категорию, а переименование потребует менять тысячи строк. Ключ хранит связь один раз и отделяет идентичность от подписи.
Образ. В операции лежит номер гардеробного жетона, а название категории — на самой вешалке.
JOINвозвращает вещи по точному номеру, не по похожему цвету пальто.
Сразу целиком
SELECT t.happened_on, a.name AS account, c.name AS category,
t.amount_tiyn / 100.0 AS amount_kzt
FROM transactions AS t
JOIN accounts AS a ON a.id = t.account_id
JOIN categories AS c ON c.id = t.category_id
ORDER BY t.happened_on, t.id;
Разбор
INNER JOIN оставляет только совпавшие строки. LEFT JOIN сохраняет каждую строку слева и подставляет NULL, когда пары справа нет. В нашей схеме обязательные внешние ключи гарантируют пару, но LEFT JOIN полезен, чтобы показать категории даже без расходов.
Связь «многие операции — одна категория» должна оставить число операций прежним. Если справа два одинаковых ключа, строки размножатся. Поэтому справочник защищён PRIMARY KEY/UNIQUE, а результат проверяется не только общей длиной: ищут отсутствующие пары и дубли ключей.
Фильтр правой таблицы после LEFT JOIN в WHERE может незаметно превратить его в INNER JOIN. Условие, которое относится к совпадению, часто должно стоять в ON.
Карта урока
Скажите своими словами
- Почему имя категории не служит внешним ключом?
- Когда нужен
LEFT JOIN? - Как связь многие-к-одному может размножить строки?
Задание
Покажите все расходные категории, включая категории без операций сентября. Для пустых категорий сумма должна быть нулём.
Куда это встанет в проекте
Отчёт связывает факты с понятными названиями, но хранит их без повторения текста.
Ответы
Показать ответы
SELECT c.name, COALESCE(SUM(t.amount_tiyn), 0) / 100.0 AS spent_kzt
FROM categories AS c
LEFT JOIN transactions AS t
ON t.category_id = c.id
AND t.happened_on >= '2026-09-01'
AND t.happened_on < '2026-10-01'
WHERE c.kind = 'expense'
GROUP BY c.id, c.name
ORDER BY c.name;
Источники
Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом
Комментарии (0)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.