Подтвердить что ты не робот

В чем разница между использованием перекрестного соединения и запятой между двумя таблицами?

В чем разница между

select * from A, B

и

select * from A cross join B

? Кажется, что они возвращают те же результаты.

Является ли вторая версия предпочтительной для первой? Является ли первая версия полностью синтаксически неправильной?

4b9b3361

Ответ 1

Они возвращают те же результаты, потому что они семантически идентичны. Это:

select * 
  from A, B

... (синтаксис) ANSI-89. Без предложения WHERE, чтобы связать таблицы вместе, результатом является декартово произведение. Именно это и обеспечивает альтернатива:

    select * 
      from A 
cross join B

... но CROSS JOIN - синтаксис ANSI-92.

О производительности

Там нет разницы в производительности.

Зачем использовать ANSI-92?

Причиной использования синтаксиса ANSI-92 является поддержка OUTER JOIN (IE: LEFT, FULL, RIGHT). Синтаксис ANSI-89 не имеет, поэтому многие базы данных реализовали свои собственные (которые не переносят на любые другие базы данных). IE: Oracle (+), SQL Server =*

Ответ 2

Они одинаковы и должны (почти) никогда не использоваться.

Ответ 3

Наткнулся на этот пост из другого вопроса SO, но большая разница заключается в создании перекрестного соединения ссылок. Например, используя cross apply или другое соединение после B в первом ( "запятая" ) варианте, крест применяется или присоединяется только к таблице (таблицам) после точки. например, следующее:

select * from A, B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

создаст ошибку:

Идентификатор с несколькими частями "A.SomeField" не может быть связан.

потому что соединение на C только привязывает к B, тогда как то же самое с перекрестным соединением...

select * from A cross join B join C on C.SomeField = A.SomeField and C.SomeField = B.SomeField 

.. считается одобренным. То же самое применимо, если используется cross apply. Например, размещение креста применимо к функции после B, функция может использовать только поля B, где тот же запрос с перекрестным соединением может использовать поля из A и B. Конечно, это также означает, что можно использовать обратное. Если вы хотите добавить соединение только для одной из таблиц, вы можете добиться этого, перейдя в "запятую" в таблицах.

Ответ 4

Первая версия изначально была единственным способом объединения двух таблиц. Но у него есть ряд проблем, поэтому ключевое слово JOIN было добавлено в стандарте ANSI-92. Они дают те же результаты, но второй более явный и должен быть предпочтительным.

Ответ 6

К комментариям относительно полезности кросс-объединений есть один очень полезный и обоснованный пример использования кросс-соединений или запятых в, по общему признанию, несколько неясном мире Postgres generate_series и Postgis-пространственного sql, где вы можете использовать перекрестное соединение с generate_series для извлечения n-й геометрии из коллекции геометрии или Multi- (Polygon/Point/Linestring), см. http://postgis.refractions.net/documentation/manual-1.4/ST_GeometryN.html

SELECT n, ST_AsEWKT(ST_GeometryN(the_geom, n)) As geomewkt
  FROM (
    VALUES (ST_GeomFromEWKT('MULTIPOINT(1 2 7, 3 4 7, 5 6 7, 8 9 10)') ),
          ( ST_GeomFromEWKT('MULTICURVE(CIRCULARSTRING(2.5 2.5,4.5 2.5, 3.5 3.5), (10 11, 12 11))') )
    )  As foo(the_geom)
CROSS JOIN generate_series(1,100) n
  WHERE n <= ST_NumGeometries(the_geom);

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

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

Ответ 7

Чтобы добавить к уже полученным ответам:

select * from A, B

Это был единственный способ присоединиться к стандарту SQL 1992 года. Поэтому, если вы хотите получить внутреннее соединение, вам нужно будет использовать предложение WHERE для критериев:

select * from A, B
where A.x = B.y;

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

select * from A, B, C, D
where B.id = C.id_b
and C.id_d = D.id;

Здесь мы имеем крест-соединение A с B/C/D. Целенаправленно или нет? Может быть, программист просто забыл and B.id = A.id_b (или что-то еще), или, может быть, эта строка была удалена по ошибке, и, возможно, она действительно была предназначена для перекрестного соединения. Кто мог сказать?

То же самое с явными объединениями

select * 
from A
cross join B
inner join C on C.id_b = B.id
inner join D on D.id = C.id_d;

Нет сомнений в намерениях программистов.

Старый синтаксис, разделенный запятыми, был заменен по уважительным причинам и больше не должен использоваться.