¿Cuál es la diferencia entre usar una combinación cruzada y poner una coma entre las dos tablas?


¿Cuál es la diferencia entre

select * from A, B

Y

select * from A cross join B

? Parecen devolver los mismos resultados.

¿ Se prefiere la segunda versión a la primera? ¿La primera versión está completamente equivocada sintácticamente?

Author: OMG Ponies, 2010-10-13

7 answers

Devuelven los mismos resultados porque son semánticamente idénticos. Esto:

select * 
  from A, B

Is es la sintaxis (wince) ANSI-89. Sin una cláusula WHERE para vincular las tablas, el resultado es un producto cartesiano. Que es exactamente lo que ofrece alternative también:

    select * 
      from A 
cross join B

...pero la COMBINACIÓN CRUZADA es la sintaxis ANSI - 92.

Acerca del Rendimiento

No hay diferencia de rendimiento entre ellos.

¿Por qué Usar ANSI-92?

La razón para usar la sintaxis ANSI-92 es para soporte de UNIÓN EXTERNA (ES DECIR: IZQUIERDA, COMPLETA, DERECHA) syntax La sintaxis ANSI-89 no tiene ninguna, por lo que muchas bases de datos implementaron la suya propia (que no se adapta a ninguna otra base de datos). IE: Oracle (+), SQL Server =*

 29
Author: OMG Ponies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 20:47:37

Son los mismos y (casi) nunca deben usarse.

 6
Author: Otávio Décio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 20:09:30

Se topó con este post de otra pregunta SO, pero una gran diferencia es la unión cruzada enlace crea. Por ejemplo, usando cross apply u otra combinación después de B en la primera variante ('coma'), la aplicación cruzada o combinación solo se referiría a la(s) tabla (s) después del punto. por ejemplo, lo siguiente:

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

Crearía un error:

El identificador de varias partes "A. someField" no pudo ser enlazado.

Porque la unión en C solo se extiende a B, mientras que lo mismo con cruz unir...

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

Is se considera aceptable. Lo mismo se aplicaría si se utiliza cross apply. Por ejemplo, colocando una aplicación cruzada en una función después de B, la función solo podría usar campos de B, donde la misma consulta con combinación cruzada, podría usar campos tanto de A como de B. Por supuesto, esto también significa que también se puede usar lo contrario. Si desea agregar un join únicamente para una de las tablas, puede lograrlo yendo 'coma' en las tablas.

 6
Author: Me.Name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-15 21:28:32

La primera versión fue originalmente la única forma de unir dos tablas. Pero tiene una serie de problemas, por lo que la palabra clave JOIN se agregó en el estándar ANSI-92. Dan los mismos resultados, pero el segundo es más explícito y es preferible.

 3
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 20:11:06

Estos son los ejemplos de cruces implícitas y explícitas. Véase http://en.wikipedia.org/wiki/Join_%28SQL%29#Cross_join .

 1
Author: Eugene Yarmash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 20:18:12

A los comentarios en cuanto a la utilidad de las uniones cruzadas, hay un ejemplo muy útil y válido de usar uniones cruzadas o comas en el mundo ciertamente algo oscuro de Postgres generate_series y Postgis spatial sql donde puede usar una unión cruzada contra generate_series para extraer la enésima geometría de una Colección de Geometría o Multi - (Polígono / Punto / Linestring), vea: 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);

Esto puede ser muy útil si desea obtener el área, centroide, cuadro delimitador o muchas de las otras operaciones que puede realizar en una sola geometría, cuando están contenidas dentro de una más grande.

Siempre he escrito tales consultas usando una coma antes de generate_series, hasta que un día me pregunté si esto realmente significaba cross join, lo que me llevó a este post. Oscuro, pero definitivamente útil.

 0
Author: John Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-03 10:06:48

Para añadir a las respuestas ya dadas:

select * from A, B

Esta era la única forma de unirse antes del estándar SQL de 1992. Así que si querías una unión interna, tendrías que usar la cláusula WHERE para los criterios:

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

Un problema con esta sintaxis era que no había un estándar para las uniones externas. Otro fue que esto se vuelve ilegible con muchas tablas y, por lo tanto, es propenso a errores y menos mantenible.

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

Aquí tenemos una unión cruzada de A con B/C/D. ¿A propósito o no? Tal vez el programador simplemente olvidó el and B.id = A.id_b (o lo que sea), o tal vez esta línea fue borrada por error, y tal vez todavía estaba destinada a ser una combinación cruzada. ¿Quién podría decirlo?

Aquí es lo mismo con joins explícitos

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

Ya no hay duda sobre las intenciones de los programadores.

La antigua sintaxis separada por comas fue reemplazada por buenas razones y no debería usarse más.

 0
Author: Thorsten Kettner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-10 07:46:38