Пошук уроків, статей та іншого контенту
Виконаєте декартовий добуток таблиць і визначите випадки, коли CROSS JOIN є доречним.
CROSS JOINCROSS JOIN виконує декартовий добуток двох таблиць: кожен рядок першої таблиці поєднується з кожним рядком другої.
Якщо перша таблиця має m рядків, а друга — n, результат міститиме:
m × nрядків.
На відміну від INNER JOIN, CROSS JOIN не використовує умову ON.
Загальний синтаксис:
SELECT
...
FROM table_a
CROSS JOIN table_b;Створимо дві таблиці: кольори та розміри товару.
DROP TABLE IF EXISTS colors;
DROP TABLE IF EXISTS sizes;
CREATE TABLE colors (
color_id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE sizes (
size_id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL
);
INSERT INTO colors (name)
VALUES
('Чорний'),
('Білий'),
('Синій');
INSERT INTO sizes (name)
VALUES
('S'),
('M'),
('L');
SELECT
colors.name AS color,
sizes.name AS size
FROM colors
CROSS JOIN sizes
ORDER BY colors.color_id, sizes.size_id;У кожного кольору буде поєднання з кожним розміром:
Чорний | S
Чорний | M
Чорний | L
Білий | S
Білий | M
Білий | L
Синій | S
Синій | M
Синій | LУсього результат міститиме 3 × 3 = 9 рядків.
Псевдоніми роблять запит коротшим і зручнішим для читання:
SELECT
c.name AS color,
s.name AS size
FROM colors AS c
CROSS JOIN sizes AS s;За наявності однакових назв стовпців псевдоніми також допомагають явно вказати, з якої таблиці потрібно взяти значення:
SELECT
c.name AS color,
s.name AS size
FROM colors AS c
CROSS JOIN sizes AS s
ORDER BY c.name, s.name;CROSS JOIN є доречнимCROSS JOIN корисний, коли потрібно отримати всі можливі комбінації елементів.
Наприклад, інтернет-магазин продає футболки в різних кольорах і розмірах. Щоб створити всі можливі варіанти:
SELECT
'Футболка' AS product_name,
c.name AS color,
s.name AS size
FROM colors AS c
CROSS JOIN sizes AS s
ORDER BY c.name, s.size_id;Такий запит лише формує комбінації в результаті. Він не додає їх автоматично до таблиці товарних варіантів.
CROSS JOIN можна використати для створення комбінацій дат і ресурсів, наприклад усіх робочих слотів для всіх кімнат.
WITH dates AS (
SELECT generate_series(
DATE '2026-09-01',
DATE '2026-09-03',
INTERVAL '1 day'
)::date AS day
),
rooms AS (
SELECT *
FROM (
VALUES
('Переговорна 1'),
('Переговорна 2')
) AS room(name)
)
SELECT
d.day,
r.name AS room
FROM dates AS d
CROSS JOIN rooms AS r
ORDER BY d.day, r.name;У результаті буде кожна дата в поєднанні з кожною кімнатою.
CROSS JOINДо результату декартового добутку можна застосувати WHERE.
SELECT
c.name AS color,
s.name AS size
FROM colors AS c
CROSS JOIN sizes AS s
WHERE c.name <> 'Білий'
ORDER BY c.color_id, s.size_id;Спочатку логічно утворюються всі комбінації, а потім рядки фільтруються умовою WHERE.
Якщо умова пов’язує стовпці двох таблиць, такий запит може бути записаний і через CROSS JOIN, і через INNER JOIN:
SELECT
a.value AS first_value,
b.value AS second_value
FROM generate_series(1, 3) AS a(value)
CROSS JOIN generate_series(1, 3) AS b(value)
WHERE a.value < b.value;Цей запит створює всі пари чисел від 1 до 3, а потім залишає лише ті, де перше число менше за друге.
У практичному коді для звичайного поєднання рядків за умовою зазвичай зрозуміліше використовувати INNER JOIN ... ON:
SELECT
a.value AS first_value,
b.value AS second_value
FROM generate_series(1, 3) AS a(value)
INNER JOIN generate_series(1, 3) AS b(value)
ON a.value < b.value;CROSS JOIN доречний, коли всі комбінації є початковим результатом, який за потреби додатково обмежується.
CROSS JOIN і INNER JOINCROSS JOIN не має умови з’єднання:
SELECT
c.name,
s.name
FROM colors AS c
CROSS JOIN sizes AS s;INNER JOIN використовує умову ON:
SELECT
p.name AS product,
c.name AS category
FROM products AS p
INNER JOIN categories AS c
ON p.category_id = c.category_id;Основна відмінність:
CROSS JOIN поєднує кожен рядок з кожним;
INNER JOIN поєднує лише рядки, для яких виконується умова ON.
Іноді CROSS JOIN можна записати через кому в секції FROM:
SELECT
c.name AS color,
s.name AS size
FROM colors AS c, sizes AS s;Це також декартовий добуток, але явний запис із CROSS JOIN кращий: він одразу показує намір запиту й зменшує ризик випадково пропустити умову з’єднання в складнішому запиті.
Декартовий добуток швидко збільшує розмір результату:
10 × 20 таблиць дадуть 200 рядків;
1 000 × 10 000 таблиць потенційно дадуть 10 000 000 рядків.
Перед виконанням великого CROSS JOIN потрібно перевірити:
чи справді потрібні всі комбінації;
чи можна відфільтрувати дані до з’єднання;
чи не містять таблиці зайвих рядків;
чи не буде результат надто великим для подальшої обробки.
Наприклад, якщо потрібно створити комбінації лише для активних кольорів і доступних розмірів, умови можна застосувати в підзапитах:
SELECT
c.name AS color,
s.name AS size
FROM (
SELECT name, color_id
FROM colors
WHERE name <> 'Білий'
) AS c
CROSS JOIN (
SELECT name, size_id
FROM sizes
WHERE name IN ('M', 'L')
) AS s
ORDER BY c.color_id, s.size_id;Тут декартовий добуток виконується вже для зменшених наборів даних.
CROSS JOIN з одним рядкомЯкщо одна сторона містить один рядок, CROSS JOIN додає його значення до кожного рядка іншої таблиці.
WITH settings AS (
SELECT
20::numeric AS tax_rate,
'UAH'::text AS currency
)
SELECT
p.product_name,
p.price,
p.price * (1 + settings.tax_rate / 100) AS price_with_tax,
settings.currency
FROM (
VALUES
('Клавіатура', 1500::numeric),
('Миша', 800::numeric)
) AS p(product_name, price)
CROSS JOIN settings;Оскільки settings містить один рядок, результат матиме стільки рядків, скільки містить набір товарів. Значення податку та валюти будуть доступні для кожного товару.
Такий підхід зручний для приєднання одного набору параметрів до всіх рядків запиту.
Кількість рядків декартового добутку можна перевірити за допомогою COUNT(*):
SELECT COUNT(*) AS combinations_count
FROM colors AS c
CROSS JOIN sizes AS s;Для трьох кольорів і трьох розмірів результат буде дорівнювати 9.
Якщо в одній із таблиць немає рядків, результат CROSS JOIN також буде порожнім:
SELECT
c.name AS color,
s.name AS size
FROM colors AS c
CROSS JOIN sizes AS s
WHERE 1 = 0;У цьому прикладі умова навмисно відкидає всі рядки.
Помилка часто виникає, коли використовується INNER JOIN, але умову ON пропущено:
-- Потенційно помилковий запит
SELECT
p.name,
c.name
FROM products AS p
JOIN categories AS c;Для JOIN без умови PostgreSQL може повідомити про помилку синтаксису залежно від форми запиту, але сама причина проблеми — відсутня логіка зв’язку між таблицями.
Якщо потрібні всі комбінації, використовуйте явний CROSS JOIN. Якщо потрібне поєднання пов’язаних рядків, додайте правильну умову ON.
Запит між великими таблицями може створити мільйони або мільярди рядків:
SELECT *
FROM large_table_a
CROSS JOIN large_table_b;Не запускайте такий запит без оцінки кількості рядків. Спочатку можна перевірити розмір таблиць:
SELECT
(SELECT COUNT(*) FROM large_table_a)
*
(SELECT COUNT(*) FROM large_table_b) AS expected_rows;CROSS JOIN замість звичайного з’єднанняЯкщо таблиці пов’язані ідентифікатором, потрібно використовувати умову:
SELECT
p.name,
c.name
FROM products AS p
INNER JOIN categories AS c
ON c.category_id = p.category_id;CROSS JOIN у такому випадку створить непотрібні комбінації товарів і категорій.
Якщо обидві таблиці мають стовпець name, краще явно вказувати джерело:
SELECT
c.name AS color_name,
s.name AS size_name
FROM colors AS c
CROSS JOIN sizes AS s;Це робить запит зрозумілішим і запобігає помилкам через неоднозначні посилання.
CROSS JOIN створює декартовий добуток двох наборів даних.
Кожен рядок першої таблиці поєднується з кожним рядком другої.
Кількість рядків дорівнює добутку кількості рядків обох таблиць.
CROSS JOIN не використовує умову ON.
Він доречний для створення всіх можливих комбінацій: варіантів товарів, дат і ресурсів, наборів параметрів.
Великий декартовий добуток може споживати багато пам’яті та часу.
Якщо потрібно поєднати лише пов’язані рядки, використовуйте INNER JOIN ... ON, а не CROSS JOIN.