¿Cuáles son los usos de Cross Join?

105

Una unión cruzada realiza un producto cartesiano en las tuplas de los dos conjuntos.

SELECT *
FROM Table1
CROSS JOIN Table2

¿Qué circunstancias hacen que esta operación SQL sea particularmente útil?

Llyle
fuente
36
Es realmente triste que esta pregunta se haya cerrado. Creo que podría llamarse Comunidad Wiki, pero decir que no es constructivo es injusto.
Wayne Koorts
1
Estoy de acuerdo. Esto respondió la pregunta exacta que tenía.
Hades
10
Hay ocasiones en las que un desarrollador más nuevo tiene problemas para comprender las implicaciones de ciertas funciones del software que está utilizando. Preguntas como esta son especialmente útiles para los desarrolladores más nuevos, principalmente porque la discusión que sigue ilumina muchas posibilidades que el desarrollador junior nunca consideró. El formato de la pregunta es elemental, en el mejor de los casos, pero la intención parece ser honesta en el sentido de que pregunta "¿por qué existe esto?" Estoy de acuerdo con Wayne Koorts, es una pena que casperOne eligiera cerrar esto y lo calificara de "no constructivo". La parte "no constructiva" me irrita particularmente.
Kaorie

Respuestas:

93

Si tiene una "cuadrícula" que desea completar por completo, como información sobre el tamaño y el color de una prenda de vestir en particular:

select 
    size,
    color
from
    sizes CROSS JOIN colors

Tal vez desee una tabla que contenga una fila por cada minuto del día y desee utilizarla para verificar que se ha ejecutado un procedimiento cada minuto, por lo que puede cruzar tres tablas:

select
    hour,
    minute
from
    hours CROSS JOIN minutes

O tiene un conjunto de especificaciones de informes estándar que desea aplicar todos los meses del año:

select
    specId,
    month
from
    reports CROSS JOIN months

El problema de mantenerlos como vistas es que, en la mayoría de los casos, no desea un producto completo, especialmente con respecto a la ropa. Puede agregar MINUSlógica a la consulta para eliminar ciertas combinaciones que no tiene, pero puede que le resulte más fácil completar una tabla de otra manera y no usar un producto cartesiano.

Además, puede terminar probando la combinación cruzada en tablas que quizás tengan algunas filas más de las que pensaba, o tal vez su WHEREcláusula faltara parcial o completamente. En ese caso, su DBA le notificará de inmediato sobre la omisión. Por lo general, él o ella no estarán felices.

Dave DuPlantis
fuente
5
... En ese caso, su DBA le notificará de inmediato sobre la omisión. Por lo general, él o ella no estarán felices. ... jaja, tan cierto!
RSW
2
@Dave: ¿El segundo ejemplo no será solo una hora CROSS JOIN minutos?
Rakesh
@Rakesh, buena captura, estaba pensando en algo más que en lo que estaba escribiendo. Fijo.
Dave DuPlantis
1
Me imagino que una unión cruzada sería muy práctica si se le dieran 2 conjuntos de identificadores (quizás en formato csv), un conjunto contendría los identificadores de los empleados y el otro los identificadores de las tareas. La idea es que tenga una tabla M2M para EmployeeTask. Puede usar la combinación cruzada para asignar cada tarea dada a cada empleado dado, siempre que haya transformado el csv en variables de tabla (o algo así).
SynBiotik
20

Genere datos para realizar pruebas.

Ovidiu Pacurar
fuente
Nunca pensé que vería una "respuesta" de 4 palabras recibir 9 votos a favor.
mickmackusa
14

Por lo general, no querrá un producto cartesiano completo para la mayoría de las consultas de bases de datos. Todo el poder de las bases de datos relacionales es que puede aplicar cualquier restricción que le pueda interesar para evitar extraer filas innecesarias de la base de datos.

Supongo que hay un ejemplo artificial en el que podría desearlo si tiene una tabla de empleados y una tabla de trabajos que deben realizarse y desea ver todas las asignaciones posibles de un empleado a un trabajo.

Cachondo
fuente
11

Ok, esto probablemente no responderá la pregunta, pero, si es cierto (y ni siquiera estoy seguro de eso) es un poco divertido de la historia.

En los primeros días de Oracle, uno de los desarrolladores se dio cuenta de que necesitaba duplicar cada fila de una tabla (por ejemplo, es posible que fuera una tabla de eventos y necesitaba cambiarlo por separado "evento de inicio" y "evento de finalización" entradas). Se dio cuenta de que si tuviera una tabla con solo dos filas, podría hacer una combinación cruzada, seleccionando solo las columnas en la primera tabla, y obtener exactamente lo que necesitaba. Así que creó una tabla simple, que naturalmente llamó "DUAL".

Más tarde, necesita hacer algo que solo se puede hacer a través de una selección de una tabla, aunque la acción en sí no tiene nada que ver con la tabla (tal vez olvidó su reloj y quiso leer la hora a través de SELECT SYSDATE FROM .. .) Se dio cuenta de que todavía tenía su mesa DUAL por ahí y la usó. Después de un tiempo, se cansó de ver la hora impresa dos veces, por lo que finalmente eliminó una de las filas.

Otros en Oracle comenzaron a usar su tabla y, finalmente, se decidió incluirla en la instalación estándar de Oracle.

Lo que explica por qué una tabla cuyo único significado es que tiene una fila tiene un nombre que significa "dos".

James Curran
fuente
8

La clave es "muéstrame todas las combinaciones posibles". Los he usado junto con otros campos calculados y luego los he ordenado / filtrado.

Por ejemplo, supongamos que está creando una aplicación de arbitraje (comercio). Tiene vendedores que ofrecen productos a un precio y compradores que piden productos a un precio. Realiza una combinación cruzada en la clave del producto (para hacer coincidir los compradores y vendedores potenciales), calcula el diferencial entre el costo y el precio, luego ordena desc. en esto para darle a usted (el intermediario) las operaciones más rentables para ejecutar. Casi siempre tendrá otros criterios de filtro delimitadores, por supuesto.

Kevin Dostalek
fuente
¡Ah! Esta explicación tiene más sentido para mí. En este caso, INNER JOIN no tiene sentido porque no hay relación entre un ID de producto y un vendedor, ya que varios vendedores pueden vender el mismo producto.
moonman239
3

Toma algo como una tabla de dígitos, que tiene diez filas para los dígitos 0-9. Puede usar la combinación cruzada en esa tabla varias veces para obtener un resultado que tenga la cantidad de filas que necesite, con los resultados numerados correctamente. Esto tiene varios usos. Por ejemplo, puede combinarlo con una función datadd () para obtener un conjunto para todos los días de un año determinado.

Joel Coehoorn
fuente
1

Imagine que tiene una serie de consultas que desea realizar sobre una combinación específica de artículos y fechas (precios, disponibilidad, etc.). Puede cargar los elementos y las fechas en tablas temporales independientes y hacer que sus consultas se unan a las tablas. Esto puede ser más conveniente que la alternativa de enumerar los elementos y las fechas en las cláusulas IN, especialmente porque algunas bases de datos limitan el número de elementos en una cláusula IN.

a fondo
fuente
1

puede usarlo CROSS JOIN para: - generar datos con fines de prueba - combinar todas las propiedades - necesita todas las combinaciones posibles de, por ejemplo, grupos sanguíneos (A, B, ..) con Rh - / +, etc ... - sintonizar para sus propósitos;) - No soy experto en esta área;)

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;
  • cree una combinación para 2 tablas sin una identificación común y luego agrúpela usando max (), etc. para encontrar la combinación más alta posible
HankerPL
fuente