← Назад к вопросам

Какое минимальное и максимальное количество строк может быть после left join?

2.0 Middle🔥 231 комментариев
#SQL и базы данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Количество строк после LEFT JOIN: минимум и максимум

Основной принцип LEFT JOIN

LEFT JOIN сохраняет ВСЕ строки из левой таблицы и добавляет соответствующие строки из правой. Результат всегда >= количество строк в левой таблице.

Минимальное количество строк

Минимум = количество строк в левой таблице

Это происходит, когда:

  1. Правая таблица пуста
  2. Условие ON не находит совпадений (строки из левой таблицы остаются с NULL в полях из правой)
  3. Между таблицами нет дубликатов при объединении

Пример:

-- Левая таблица: 5 строк
SELECT * FROM users
-- id | name
-- 1  | Alice
-- 2  | Bob
-- 3  | Charlie
-- 4  | David
-- 5  | Eve

-- Правая таблица: 2 строки
SELECT * FROM orders
-- id | user_id | amount
-- 101| 1       | 100
-- 102| 2       | 200

-- LEFT JOIN: результат 5 строк (количество юзеров)
SELECT u.id, u.name, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- Результат:
-- id | name    | amount
-- 1  | Alice   | 100
-- 2  | Bob     | 200
-- 3  | Charlie | NULL
-- 4  | David   | NULL
-- 5  | Eve     | NULL

Вывод: хотя в orders только 2 строки, результат имеет 5 строк (как и левая таблица).

Максимальное количество строк

Максимум = количество строк в левой таблице × количество совпадений в правой таблице

Это происходит, когда для каждой строки левой таблицы находится несколько совпадений в правой таблице.

Пример с дубликатами в правой таблице:

-- Левая таблица: 3 строки
SELECT * FROM customers
-- customer_id | name
-- 1           | Alice
-- 2           | Bob
-- 3           | Charlie

-- Правая таблица: 5 строк (дубликаты по customer_id)
SELECT * FROM purchases
-- purchase_id | customer_id | amount
-- 101         | 1           | 100
-- 102         | 1           | 150    <- второй заказ Alice
-- 103         | 1           | 200    <- третий заказ Alice
-- 104         | 2           | 300
-- 105         | 2           | 400    <- второй заказ Bob

-- LEFT JOIN: результат 5 строк!
SELECT c.customer_id, c.name, p.purchase_id, p.amount
FROM customers c
LEFT JOIN purchases p ON c.customer_id = p.customer_id;

-- Результат:
-- customer_id | name    | purchase_id | amount
-- 1           | Alice   | 101         | 100
-- 1           | Alice   | 102         | 150
-- 1           | Alice   | 103         | 200
-- 2           | Bob     | 104         | 300
-- 2           | Bob     | 105         | 400
-- 3           | Charlie | NULL        | NULL

Формула: Максимум строк = SUM(количество совпадений для каждой левой строки)

Критические случаи

Случай 1: Дубликаты в левой таблице

-- Левая таблица: 4 строки (дубликат user_id=1)
users:
-- user_id | name
-- 1       | Alice
-- 1       | Alice (дубликат!)
-- 2       | Bob
-- 3       | Charlie

-- Правая таблица: 2 строки
orders:
-- order_id | user_id | amount
-- 101      | 1       | 100
-- 102      | 2       | 200

-- LEFT JOIN результат: 5 строк!
SELECT u.user_id, u.name, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- Результат:
-- user_id | name    | amount
-- 1       | Alice   | 100      <- совпадение для первой Alice
-- 1       | Alice   | 100      <- совпадение для дубликата Alice
-- 2       | Bob     | 200
-- 3       | Charlie | NULL
-- (5 строк!)

Вывод: дубликаты в левой таблице приводят к дубликатам в результате.

Случай 2: Дубликаты в обеих таблицах

-- Левая: 3 строки (дубликат)
users:
-- id | name
-- 1  | Alice
-- 1  | Alice (дубликат)
-- 2  | Bob

-- Правая: 2 строки (дубликаты)
orders:
-- id | user_id | amount
-- 101| 1       | 100
-- 102| 1       | 150    <- второй заказ user_id=1

-- LEFT JOIN: 4 строки!
SELECT *
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- Результат:
-- id | name  | id  | user_id | amount
-- 1  | Alice | 101 | 1       | 100     <- Alice(1) x order(101)
-- 1  | Alice | 102 | 1       | 150     <- Alice(1) x order(102)
-- 1  | Alice | 101 | 1       | 100     <- Alice(1-дубликат) x order(101)
-- 1  | Alice | 102 | 1       | 150     <- Alice(1-дубликат) x order(102)
-- 2  | Bob   | NULL| NULL    | NULL

Формула для этого случая:

  • Alice(1) в левой: 2 строки
  • Заказы для user_id=1: 2 строки
  • Результат: 2 × 2 = 4 строки на Alice
  • Plus Bob (1 строка) = 5 строк

Случай 3: Составное условие ON

-- Левая: 3 строки
users:
-- id | country
-- 1  | USA
-- 2  | USA
-- 3  | UK

-- Правая: 4 строки
orders:
-- id | user_id | country | amount
-- 101| 1       | USA     | 100
-- 102| 1       | USA     | 150    <- дубликат для user_id=1, USA
-- 103| 2       | USA     | 200
-- 104| 2       | UK      | 250    <- разная страна

-- LEFT JOIN с составным условием
SELECT *
FROM users u
LEFT JOIN orders o ON u.id = o.user_id AND u.country = o.country;

-- Результат:
-- u.id | u.country | o.id | o.user_id | o.country | amount
-- 1    | USA       | 101  | 1         | USA       | 100
-- 1    | USA       | 102  | 1         | USA       | 150      <- совпадает по обоим условиям
-- 2    | USA       | 103  | 2         | USA       | 200
-- 2    | USA       | NULL | NULL      | NULL      | NULL     <- order для user_id=2 имеет UK, не совпадает
-- 3    | UK        | NULL | NULL      | NULL      | NULL     <- нет заказов для UK

-- Итого: 5 строк

Чистая математика LEFT JOIN

Минимум строк = количество строк в левой таблице
Максимум строк = количество строк в левой × максимум повторений в правой

Примеры:

Left rowsMax matches per left rowResult rows
10110-10
10510-50
1002100-200
10000 (no matches)1000

Как узнать максимум совпадений?

-- Проверка дубликатов в правой таблице
SELECT join_key, COUNT(*) as match_count
FROM right_table
GROUP BY join_key
ORDER BY match_count DESC;

-- Если есть join_key с count > 1, то будут дубликаты в результате

Пример:

-- Проверим orders на дубликаты user_id
SELECT user_id, COUNT(*) as order_count
FROM orders
GROUP BY user_id
ORDER BY order_count DESC;

-- Результат:
-- user_id | order_count
-- 1       | 3           <- максимум 3 заказа для одного пользователя
-- 2       | 2
-- 5       | 1

-- Итого: левая таблица (users) может иметь до N×3 строк, где N = количество пользователей

Практические советы для аналитика

1. Всегда проверяй дубликаты перед JOIN

-- Проверка дубликатов в обеих таблицах
SELECT 
    'left' as table_name,
    join_key,
    COUNT(*) as duplicate_count
FROM left_table
GROUP BY join_key
HAVING COUNT(*) > 1

UNION ALL

SELECT 
    'right' as table_name,
    join_key,
    COUNT(*)
FROM right_table
GROUP BY join_key
HAVING COUNT(*) > 1;

2. Использует DISTINCT если нужны уникальные строки

-- Если нужны уникальные пользователи (без дубликатов заказов)
SELECT DISTINCT u.user_id, u.name
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

3. Используй COUNT для проверки результата

-- Сравни количество строк
SELECT COUNT(*) FROM left_table;         -- ожидаемый минимум
SELECT COUNT(*) FROM (
    SELECT *
    FROM left_table l
    LEFT JOIN right_table r ON ...
) result;                                  -- фактический результат

4. Внимание на NULL при подсчёте

-- После LEFT JOIN с NULL значениями
SELECT 
    COUNT(*) as total_rows,              -- включает NULL
    COUNT(right_id) as non_null_rows,    -- исключает NULL
    COUNT(*) - COUNT(right_id) as null_rows
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

Заключение

LEFT JOIN ГАРАНТИРУЕТ:

  • Минимум: все строки из левой таблицы (никогда не меньше)
  • Максимум: все строки из левой × максимум совпадений в правой

Дубликаты в правой таблице — основная причина неожиданного роста строк. Всегда проверяй их перед написанием JOIN!

Какое минимальное и максимальное количество строк может быть после left join? | PrepBro