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

Как работает CROSS JOIN?

1.6 Junior🔥 111 комментариев
#Базы данных (SQL)

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

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

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

CROSS JOIN в SQL

CROSS JOIN (декартово произведение) — это соединение, которое создаёт все возможные комбинации строк из двух таблиц. Это одна из самых редко используемых операций, но она полезна в определённых сценариях.

Как работает CROSS JOIN

Базовый пример:

-- Таблица 1: colors (2 строки)
id | color
1  | Red
2  | Blue

-- Таблица 2: sizes (3 строки)
id | size
1  | Small
2  | Medium
3  | Large

-- CROSS JOIN
SELECT colors.color, sizes.size
FROM colors
CROSS JOIN sizes;

-- Результат: 2 * 3 = 6 комбинаций
color | size
Red   | Small
Red   | Medium
Red   | Large
Blue  | Small
Blue  | Medium
Blue  | Large

Формула: Если в таблице A есть N строк, в таблице B есть M строк, то результат содержит N × M строк.

Синтаксис

-- Способ 1: Явный CROSS JOIN
SELECT *
FROM table1
CROSS JOIN table2;

-- Способ 2: Запятая (старый синтаксис, но работает)
SELECT *
FROM table1, table2;

-- Оба варианта идентичны

Практические применения

1. Генерация всех комбинаций (e-commerce)

-- У нас есть: цвета и размеры товара
-- Нужно: создать все вариации товара

SELECT 
    p.product_id,
    p.product_name,
    c.color,
    s.size,
    CONCAT(p.product_name, ' - ', c.color, ' - ', s.size) as variant_name
FROM products p
CROSS JOIN colors c
CROSS JOIN sizes s
WHERE p.product_id = 1;

-- Результат:
product_id | product_name | color | size   | variant_name
1          | Shirt        | Red   | Small  | Shirt - Red - Small
1          | Shirt        | Red   | Medium | Shirt - Red - Medium
1          | Shirt        | Red   | Large  | Shirt - Red - Large
1          | Shirt        | Blue  | Small  | Shirt - Blue - Small
1          | Shirt        | Blue  | Medium | Shirt - Blue - Medium
1          | Shirt        | Blue  | Large  | Shirt - Blue - Large

2. Создание матрицы расписания

-- Нужно: создать все слоты времени для расписания

SELECT 
    d.calendar_date,
    t.time_slot
FROM dates d
CROSS JOIN time_slots t
WHERE d.calendar_date BETWEEN '2024-01-01' AND '2024-01-31'
ORDER BY d.calendar_date, t.time_slot;

-- Результат: для каждого дня все временные слоты
calendar_date | time_slot
2024-01-01    | 09:00
2024-01-01    | 10:00
2024-01-01    | 11:00
2024-01-02    | 09:00
2024-01-02    | 10:00

3. Декартово произведение для анализа

-- Сравнение всех продуктов между собой
SELECT 
    p1.product_id as product1_id,
    p1.product_name as product1,
    p2.product_id as product2_id,
    p2.product_name as product2,
    ABS(p1.price - p2.price) as price_difference
FROM products p1
CROSS JOIN products p2
WHERE p1.product_id < p2.product_id  -- Избегаем дубликатов
ORDER BY price_difference DESC;

-- Результат: сравнение цен всех товаров
product1_id | product1  | product2_id | product2   | price_difference
1           | Laptop    | 3           | Mouse      | 990
2           | Keyboard  | 3           | Mouse      | 75

4. Генерация тестовых данных

# Python пример с CROSS JOIN
from sqlalchemy import select, text

# Нужно создать 1000 записей для теста
result = session.execute(
    text("""
    SELECT 
        ROW_NUMBER() OVER () as id,
        g1.val * 100 + g2.val as user_id,
        'test_user_' || (g1.val * 100 + g2.val) as username
    FROM 
        generate_series(0, 9) g1(val)
        CROSS JOIN generate_series(0, 9) g2(val)
    """)
)

# Результат: 100 строк (10 * 10)
for row in result:
    print(row)  # (1, 0, 'test_user_0'), (2, 1, 'test_user_1'), ...

CROSS JOIN vs INNER JOIN

-- CROSS JOIN (декартово произведение)
SELECT *
FROM users
CROSS JOIN orders;
-- Результат: КАЖДОГО пользователя с КАЖДЫМ заказом (N × M)
-- Это обычно неправильно!

-- INNER JOIN (по связи)
SELECT *
FROM users
INNER JOIN orders ON users.id = orders.user_id;
-- Результат: каждый пользователь только со своими заказами
-- Это правильно!

Осторожность: Взрывной рост данных

Проблема:

-- Небольшие таблицы
TABLE A: 100 строк
TABLE B: 100 строк
TABLE C: 100 строк

-- CROSS JOIN
SELECT * FROM A CROSS JOIN B CROSS JOIN C;

-- Результат: 100 × 100 × 100 = 1,000,000 строк!
-- Если ещё одна таблица из 100 строк:
-- 100 × 100 × 100 × 100 = 100,000,000 строк (память, время, лаги)

Поэтому CROSS JOIN нужно использовать осторожно:

-- ❌ Опасно
SELECT COUNT(*)
FROM large_table1
CROSS JOIN large_table2;
-- Может занять часы и "зависнуть" сервер

-- ✅ Безопаснее с LIMIT
SELECT *
FROM large_table1
CROSS JOIN large_table2
LIMIT 1000;

Практический пример: Django ORM

from django.db.models import F
from myapp.models import Color, Size, Product

# Получить все комбинации
variants = Product.objects.raw(
    """
    SELECT 
        p.id,
        p.name,
        c.color,
        s.size
    FROM products p
    CROSS JOIN colors c
    CROSS JOIN sizes s
    WHERE p.category = %s
    """,
    ['shirts']
)

for variant in variants:
    print(f"{variant.name} - {variant.color} - {variant.size}")

Когда НЕ использовать CROSS JOIN

❌ Типичная ошибка:

-- Забыл условие join
SELECT *
FROM orders
CROSS JOIN customers;
-- Результат: каждый заказ с каждым клиентом (неправильно!)

-- Правильно
SELECT *
FROM orders
INNER JOIN customers ON orders.customer_id = customers.id;

❌ Случайный CROSS JOIN в цикле:

# Плохо
for user in users:  # 1000 users
    for order in orders:  # 10000 orders
        print(user.id, order.id)  # 10,000,000 комбинаций!

# Хорошо (SQL)
SELECT * FROM users INNER JOIN orders ON users.id = orders.user_id;

Резюме

CROSS JOIN нужен для:

  • Генерации всех комбинаций (варианты товаров)
  • Создания матриц (расписание, календари)
  • Декартовых произведений для анализа
  • Генерации тестовых данных

Осторожно с:

  • Большими таблицами (может быть 1M+ результатов)
  • Непреднамеренными CROSS JOINами (забыл условие)
  • Производительностью (нужен LIMIT для safety)

Правило: Если случайно сделал CROSS JOIN и запрос зависает — добавь LIMIT 1000 для проверки, потом оптимизируй.