Добавить в корзинуПозвонить
Найти в Дзене
Информатика

JOIN: как одна команда SQL управляет рекомендациями Netflix, выдачей TikTok и подбором матчей в играх

Ты сейчас откроешь TikTok — и за 30 миллисекунд алгоритм решит, что тебе показать. Не человек. Не случай. Запрос к базе данных. Именно там, под капотом любого цифрового продукта, живёт SQL. И самая мощная его часть — это JOIN. Представь: у Spotify есть 100 миллионов пользователей и 80 миллионов треков. Хранить всё в одной гигантской таблице — это как свалить в одну комнату весь Ikea. Технически возможно. Практически — катастрофа. Поэтому данные живут в разных таблицах: пользователи отдельно, треки отдельно, история прослушиваний отдельно, подписки отдельно. Каждая таблица отвечает за своё. Проблема: когда тебе нужен ответ — «какие треки слушал этот пользователь за последний месяц и какие из них входят в его подписку» — данные нужно собрать вместе. Вот тут и появляется JOIN. На низком уровне любой JOIN — это перебор: берём каждую строку из первой таблицы, ищем совпадение во второй. Звучит банально? Но именно этот механизм стоит за: Ты не видишь этот запрос. Но он выполняется каждый раз,
Оглавление
Данные разбиты на части
Данные разбиты на части

Ты сейчас откроешь TikTok — и за 30 миллисекунд алгоритм решит, что тебе показать. Не человек. Не случай. Запрос к базе данных.

Именно там, под капотом любого цифрового продукта, живёт SQL. И самая мощная его часть — это JOIN.

Сначала — почему данные вообще разбиты на части

Представь: у Spotify есть 100 миллионов пользователей и 80 миллионов треков. Хранить всё в одной гигантской таблице — это как свалить в одну комнату весь Ikea. Технически возможно. Практически — катастрофа.

Поэтому данные живут в разных таблицах: пользователи отдельно, треки отдельно, история прослушиваний отдельно, подписки отдельно. Каждая таблица отвечает за своё.

Проблема: когда тебе нужен ответ — «какие треки слушал этот пользователь за последний месяц и какие из них входят в его подписку» — данные нужно собрать вместе.

Вот тут и появляется JOIN.

JOIN — это не «соединить таблички». Это собрать реальность из фрагментов

JOIN — собрать реальность из фрагментов
JOIN — собрать реальность из фрагментов

На низком уровне любой JOIN — это перебор: берём каждую строку из первой таблицы, ищем совпадение во второй. Звучит банально? Но именно этот механизм стоит за:

  • рекомендательными системами — когда Netflix матчит твою историю просмотров с профилями похожих пользователей
  • подбором матчей в Dota или Valorant — когда сервер соединяет таблицу игроков с таблицей рейтингов и очереди
  • фильтрацией ленты в Instagram* — когда алгоритм соединяет посты с твоими подписками, реакциями и временем суток

Ты не видишь этот запрос. Но он выполняется каждый раз, когда ты открываешь приложение.

Четыре режима — четыре разных взгляда на данные

Четыре режима JOIN
Четыре режима JOIN

INNER JOIN — строгий. Возвращает только то, что есть в обеих таблицах одновременно. Как пересечение двух кругов Венна. Именно так работает поиск: «покажи мне треки, которые есть в моей библиотеке и доступны в моей стране».

LEFT JOIN — мягкий. Берёт всё из первой таблицы и добавляет совпадения из второй. Нет совпадения? Ставит NULL. Именно через LEFT JOIN аналитики находят дыры в данных — например, пиццерии, которые никто не посещал, или товары, на которые нет ни одного заказа. Это не баг — это инсайт.

FULL OUTER JOIN — тотальный. Отдаёт всё из обеих таблиц, с совпадениями и без. Редкий, но мощный — когда нужна полная картина без исключений. Представь аудит: ни один пользователь и ни одна транзакция не должны выпасть из отчёта.

CROSS JOIN — взрывной 💥. Декартово произведение: каждая строка первой таблицы × каждая строка второй. Из 1000 строк и 1000 строк — миллион комбинаций. Используется редко, но незаменим для генерации всех возможных вариантов. Например, всех дат за месяц, чтобы потом найти — в какие из них ничего не происходило.

NULL — это не ноль и не пустота. Это «неизвестно»

NULL — отсутствие как данные
NULL — отсутствие как данные

Один из самых недооценённых инсайтов в работе с данными.

Когда после LEFT JOIN появляется NULL — это не ошибка. Это информация. Отсутствие данных само по себе является данными.

Именно поэтому в SQL нельзя написать WHERE column = NULL. Это всегда даст пустой результат — потому что NULL не равен ничему, даже самому себе. Нужно IS NULL.

Звучит как придирка? Именно это незнание ломает запросы у 80% новичков.

CTE: как сделать из хаоса — архитектуру

CTE — архитектура запроса
CTE — архитектура запроса

Когда запрос становится сложным, его можно разбить на именованные блоки с помощью WITH. Это называется Common Table Expression — и это меняет всё.

Вместо одного запроса-монстра на 50 строк — несколько чистых, читаемых шагов. Как функции в коде. Каждый блок решает одну задачу, следующий берёт результат и идёт дальше.

WITH all_days AS (
-- шаг 1: генерируем все даты
SELECT generate_series('2022-01-01'::DATE, '2022-01-10'::DATE, '1 day')::DATE AS day
),
visited AS (
-- шаг 2: берём только дни с посещениями
SELECT DISTINCT visit_date FROM person_visits WHERE person_id IN (1, 2)
)
-- шаг 3: находим пропуски
SELECT day AS missing_date
FROM all_days
LEFT JOIN visited ON day = visit_date
WHERE visit_date IS NULL;

Посмотри на этот запрос. Он находит дни, когда данных нет. Это и есть аналитика — умение увидеть не только то, что есть, но и то, чего не хватает.

Почему это важно прямо сейчас

SQL не устарел. Он не «для бухгалтеров» и не «для старых систем».

Каждый дата-аналитик, каждый backend-разработчик, каждый продакт-менеджер в серьёзной компании пишет SQL или читает его. Финтех, маркетплейсы, стриминги, игровые платформы, медицина — везде база данных, везде запросы.

И когда ты понимаешь, как работает JOIN — ты начинаешь видеть, как устроена цифровая реальность. Не магия. Не алгоритм за семью печатями. Логика. Структура. Данные.

Это и есть контроль.

🔥 Хочешь копнуть глубже? Полный учебный материал с детальными примерами, схемами и разбором всех типов JOIN ждёт тебя на нашем сайте!