Какое использование перекрестного соединения?

106

Перекрестное соединение выполняет декартово произведение кортежей двух наборов.

SELECT *
FROM Table1
CROSS JOIN Table2

Какие обстоятельства делают такую ​​операцию SQL особенно полезной?

Llyle
источник
37
Очень жаль, что этот вопрос закрыли. Я думаю, что это могло быть отмечено как «Community Wiki», но сказать, что это неконструктивно, было бы несправедливо.
Уэйн Коортс
1
Я согласен. Это ответило на мой вопрос.
Hades
10
Бывают случаи, когда начинающий разработчик не может понять значения определенных функций программного обеспечения, которое он использует. Подобные вопросы особенно полезны для новых разработчиков, прежде всего потому, что последующее обсуждение освещает многие возможности, которые младший разработчик никогда не рассматривал. Формат вопроса в лучшем случае элементарный, но намерение кажется честным в том, что он спрашивает: «Почему это вообще существует?» Я согласен с Уэйном Кортом, очень жаль, что casperOne решили закрыть это дело и назвали его «неконструктивным». «Неконструктивная» часть меня особенно раздражает.
Kaorie

Ответы:

93

Если у вас есть «сетка», которую вы хотите заполнить полностью, например информацию о размере и цвете для определенного предмета одежды:

select 
    size,
    color
from
    sizes CROSS JOIN colors

Возможно, вам нужна таблица, которая содержит строку для каждой минуты дня, и вы хотите использовать ее для проверки того, что процедура выполняется каждую минуту, поэтому вы можете пересечь три таблицы:

select
    hour,
    minute
from
    hours CROSS JOIN minutes

Или у вас есть набор стандартных спецификаций отчетов, которые вы хотите применять каждый месяц в году:

select
    specId,
    month
from
    reports CROSS JOIN months

Проблема с сохранением этих представлений в том, что в большинстве случаев вам не нужен законченный продукт, особенно в отношении одежды. Вы можете добавить MINUSлогику в запрос, чтобы удалить определенные комбинации, которые у вас нет, но вам может быть проще заполнить таблицу каким-либо другим способом и не использовать декартово произведение.

Кроме того, вы можете попробовать перекрестное соединение для таблиц, которые, возможно, имеют на несколько строк больше, чем вы думали, или, возможно, ваше WHEREпредложение частично или полностью отсутствует. В этом случае ваш администратор баз данных незамедлительно уведомит вас об упущении. Обычно он или она не будут счастливы.

Дэйв ДюПлантис
источник
5
... В этом случае ваш администратор баз данных незамедлительно уведомит вас об упущении. Обычно он или она не будут счастливы. ... ха-ха, это правда!
RSW
2
@ Дэйв: Разве второй пример не займет всего час CROSS JOIN минут?
Ракеш
@ Ракеш, хороший улов, я думал не о том, что печатал. Исправлена.
Дэйв ДюПлантис
1
Я могу представить, что перекрестное соединение было бы очень практичным, если бы вам было дано 2 набора идентификаторов (возможно, в формате csv), один набор содержал бы идентификаторы сотрудников, а другой - идентификаторы задач. Идея в том, что у вас есть таблица M2M для EmployeeTask. Вы можете использовать перекрестное соединение, чтобы назначить каждую задачу каждому заданному сотруднику, если вы преобразовали CSV в переменные таблицы (или что-то еще).
SynBiotik 05
20

Сгенерируйте данные для тестирования.

Овидиу Пакурар
источник
Я никогда не думал, что увижу «ответ» из 4 слов и получу 9 голосов.
mickmackusa 03
14

Обычно вам не понадобится полный декартово произведение для большинства запросов к базе данных. Вся сила реляционных баз данных заключается в том, что вы можете применять любые ограничения, которые могут вас заинтересовать, чтобы избежать извлечения ненужных строк из базы данных.

Я предполагаю, что есть один надуманный пример, когда вы можете захотеть, если у вас есть таблица сотрудников и таблица вакансий, которые нужно выполнить, и вы хотите увидеть все возможные назначения одного сотрудника на одну работу.

Рэнди
источник
11

Хорошо, это, вероятно, не ответит на вопрос, но, если это правда (а я даже не уверен в этом), это забавная история.

На заре Oracle один из разработчиков понял, что ему нужно дублировать каждую строку в таблице (например, возможно, это была таблица событий, и ему нужно было изменить ее отдельно «начальное событие» и «конечное событие») записи). Он понял, что если бы у него была таблица с двумя строками, он мог бы выполнить перекрестное соединение, выбрав только столбцы в первой таблице, и получить именно то, что ему было нужно. Поэтому он создал простую таблицу, которую, естественно, назвал «ДВОЙНОЙ».

Позже ему нужно сделать что-то, что можно было бы сделать только с помощью выбора из таблицы, даже если само действие не имело ничего общего с таблицей (возможно, он забыл свои часы и хотел прочитать время с помощью SELECT SYSDATE FROM .. .) Он понял, что у него все еще валяется его ДВОЙНОЙ стол, и использовал его. Через некоторое время ему надоело видеть, как время печатается дважды, поэтому он в конце концов удалил одну из строк.

Другие в Oracle начали использовать его таблицу, и в конце концов было решено включить ее в стандартную установку Oracle.

Это объясняет, почему таблица, единственное значение которой состоит в том, что в ней есть одна строка, имеет имя, означающее «две».

Джеймс Карран
источник
8

Ключ - «покажи мне все возможные комбинации». Я использовал их вместе с другими вычисляемыми полями и затем отсортировал / отфильтровал их.

Например, предположим, что вы создаете приложение для арбитража (торговли). У вас есть продавцы, предлагающие товары по цене, а покупатели просят товары по цене. Вы выполняете перекрестное соединение по ключу продукта (чтобы сопоставить потенциальных покупателей и продавцов), вычисляете разницу между стоимостью и ценой, затем сортируете по убыванию. чтобы дать вам (посреднику) наиболее прибыльные сделки для исполнения. Конечно, почти всегда у вас будут другие критерии ограничивающего фильтра.

Кевин Досталек
источник
Ах! Это объяснение имеет для меня наибольший смысл. В этом случае ВНУТРЕННЕЕ СОЕДИНЕНИЕ не имеет смысла, поскольку нет связи между идентификатором продукта и продавцом, поскольку несколько продавцов могут продавать один и тот же продукт.
moonman239
3

Принимает что-то вроде таблицы цифр, в которой десять строк для цифр 0–9. Вы можете использовать перекрестное соединение для этой таблицы несколько раз, чтобы получить результат, который содержит необходимое вам количество строк с соответствующими номерами результатов. Это имеет ряд применений. Например, вы можете объединить его с функцией datadd (), чтобы получить набор для каждого дня в заданном году.

Джоэл Кохорн
источник
1

Представьте, что у вас есть серия запросов, которые вы хотите задать по определенной комбинации товаров и дат (цены, наличие и т. Д.). Вы можете загружать элементы и даты в отдельные временные таблицы, а ваши запросы перекрестно объединять таблицы. Это может быть более удобным, чем альтернатива перечисления элементов и дат в предложениях IN, тем более что некоторые базы данных ограничивают количество элементов в предложении IN.

тщательно
источник
1

вы можете использовать его CROSS JOIN, чтобы: - генерировать данные для целей тестирования - комбинировать все свойства - вам нужны все возможные комбинации, например, группы крови (A, B, ..) с Rh - / + и т. д. - настроить его для ваших целей;) - Я не специалист в этой области;)

CREATE TABLE "HR"."BL_GRP_01" 
("GR_1" VARCHAR2(5 BYTE));
REM INSERTING into BL_GRP_01
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_01 (GR_1) values (NULL);

CREATE TABLE "HR"."BL_GRP_02" 
("GR_1" VARCHAR2(5 BYTE));

REM INSERTING into BL_GRP_02
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_02 (GR_1) values (NULL);

CREATE TABLE "HR"."RH_VAL_01" 
("RH_VAL" VARCHAR2(5 BYTE));
REM INSERTING into RH_VAL_01
SET DEFINE OFF;
Insert into RH_VAL_01 (RH_VAL) values ('+');
Insert into RH_VAL_01 (RH_VAL) values ('-');
Insert into RH_VAL_01 (RH_VAL) values (NULL);

select distinct  a.GR_1 || b.GR_1 || c.RH_VAL as BL_GRP
from BL_GRP_01 a, BL_GRP_02 b, RH_VAL_01 c
GROUP BY a.GR_1, b.GR_1, c.RH_VAL;
  • создать соединение для 2 таблиц без общего идентификатора, а затем сгруппировать его с помощью max () и т. д., чтобы найти максимально возможную комбинацию
HankerPL
источник