CROSS JOIN — это все, что нам нужно?

Если бы мы избавились от INNER JOIN, LEFT JOIN. RIGHT JOIN и FULL JOIN завтра, можем ли мы полностью заменить их функционал на CROSS JOIN и фильтры на нем? Сначала я думал, что мы, очевидно, можем, но крайние случаи, такие как этот, вызвали у меня сомнения.

это плохая идея, перекрестное соединение требует много памяти и времени, чтобы заменить, например, внутреннее соединение, а также ЛЕВОЕ и ПРАВОЕ СОЕДИНЕНИЕ не могут быть заменены перекрестным соединением.

nbk 12.08.2023 01:16

Зачем тебе CROSS JOIN???

Eric 12.08.2023 01:22

Старый синтаксис ANSI-89 для достижения этой цели был объявлен устаревшим в 2008 году и удален в 2012 году; зачем нам снова возвращаться в 1989 год?

Thom A 12.08.2023 10:59

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

siggemannen 12.08.2023 11:15

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

Martin Smith 12.08.2023 11:20
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
3
5
89
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

LEFT JOIN нельзя заменить на CROSS JOIN

a
_
1
2

b
_
1
4

a left join b is

1,1
2,null

который не является подмножеством a cross join b

Ответ принят как подходящий
a  b
1  1
2  4

ПРИСОЕДИНИТЬСЯ

1, 1

ЛЕВОЕ СОЕДИНЕНИЕ

1, 1
2, NULL

ПРАВОЕ ПРИСОЕДИНЕНИЕ

1, 1
NULL, 4

ПОЛНОЕ СОЕДИНЕНИЕ

1, 1
2, NULL
NULL, 4

ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ

1, 1
1, 4
2, 1
2, 4

Как вы собираетесь получить LEFT JOIN от CROSS JOIN?

«Как вы собираетесь получить LEFT JOIN от CROSS JOIN?» - здесь невозможно. Оцените результат a = b по всем строкам перекрестного соединения. Это возвращает 1, 1 - отслеживайте все отдельные строки слева, соответствуют ли они чему-либо, обратите внимание, что a = 2 никогда ничему не соответствует, поэтому его необходимо сохранить для семантики внешнего соединения и что нам нужно вывести 2, NULL.

Martin Smith 12.08.2023 13:18

Нет, это не логически «все, что нам нужно».

Логически INNER JOIN — это просто CROSS JOIN с предикатом соединения, оцениваемым во всех строках.

  • Для левых внешних соединений для любых строк в левой таблице, которые ничему не соответствуют, выведите их со значениями NULL для столбцов правой таблицы.
  • Для правых внешних соединений для любых строк в правой таблице, которые ничему не соответствуют, выведите их со значениями NULL для столбцов левой таблицы.
  • Полные внешние соединения сочетают в себе оба этих поведения.

В большинстве случаев, если бы вам был представлен результат CROSS JOIN между таблицами A и B, и он содержал бы идентификатор строки для обеих таблиц A и B, тогда он содержал бы достаточно информации, чтобы вычислить, каким должен быть результат внешнего соединения для определенного предиката соединения ( хотя SQL для этого был бы неэффективен)

Например для

DECLARE @A TABLE 
(
A_ID INT PRIMARY KEY,
A_N INT
)

DECLARE @B TABLE 
(
B_ID INT PRIMARY KEY,
B_N INT
)

INSERT @A
VALUES (1, 101),
       (2, 101),
       (3, 102),
       (4, 102);

INSERT @B
VALUES (1, 101),
       (2, 101);

Тогда один из способов имитации

SELECT *
FROM @A A
LEFT JOIN @B B ON A.A_N = B.B_N;

будет (DB Fiddle)

WITH A_cross_join_B AS
(
SELECT *
FROM @A A
CROSS JOIN @B B 
), A_cross_join_B_with_loj_flag AS
(
SELECT *, 
        /*2 if Join predicate matches, 1 if we are preserving a single instance of this row for outer join purposes, 0 otherwise*/
        Flag = CASE WHEN A_N = B_N THEN 2 ELSE CASE WHEN 1 = ROW_NUMBER() OVER (PARTITION BY A_ID ORDER BY CASE WHEN A_N = B_N THEN 0 ELSE 1 END) THEN 1 ELSE 0 END END
FROM A_cross_join_B
)
SELECT A_ID, 
       A_N, 
       B_ID = CASE WHEN Flag = 2 THEN B_ID END, 
       B_N = CASE WHEN Flag = 2 THEN B_N END
FROM A_cross_join_B_with_loj_flag
WHERE Flag <> 0

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

В общем случае каждая строка из таблицы A будет представлена ​​b_card раз, где b_card — количество строк в таблице B. Аналогичным образом каждая строка из таблицы B будет представлена ​​a_card раз.

Если и a_card, и b_card равны >=1, то присутствуют все исходные строки.

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

Да, это было бы хорошо. Старый синтаксис запятой, который появился до того, как объединение стало словом, именно таков.

select *
from
tableA A, tableB B
where
A.Id = B.Id

Я не вижу ничего, что вы не можете сделать с этим

Другие вопросы по теме