sql >> Base de Datos >  >> RDS >> Database

Su guía definitiva para SQL Join:CROSS JOIN - Parte 3

CROSS JOIN está en el centro de atención. Este artículo finaliza nuestra pequeña serie de publicaciones relacionadas con SQL JOIN. Si se perdió los dos artículos anteriores, consúltelos de la siguiente manera:

  • Tu guía definitiva para SQL Join - Parte 1:INNER JOIN
  • Su guía definitiva para SQL Join - Parte 2:OUTER JOIN

SQL Server CROSS JOIN es la más simple de todas las uniones. Implementa una combinación de 2 tablas sin una condición de unión. Si tiene 5 filas en una tabla y 3 filas en otra, obtiene 15 combinaciones. Otra definición es un producto cartesiano.

Ahora, ¿por qué querría combinar tablas sin una condición de combinación? Espera un poco porque estamos llegando. Primero, consultemos la sintaxis.

Sintaxis SQL CROSS JOIN

Al igual que con INNER JOIN, puede tener un CROSS JOIN de 2 estándares, SQL-92 y SQL-89. T-SQL admite ambas sintaxis, pero prefiero SQL-92. Consulta la parte 1 dedicada a INNER JOIN si quieres saber por qué.

Sintaxis SQL-92

SELECT
 a.column1
,b.column2
FROM Table1 a
CROSS JOIN Table2 b

SQL-89

SELECT
 a.column1
,b.column2
FROM Table1 a, Table2 b 

Muy parecido a SQL-89:INNER JOIN sin la condición de unión.

5 ejemplos de uso de SQL Server CROSS JOIN

Quizás se pregunte cuándo puede usar SQL CROSS JOIN. Por supuesto, es útil para dar forma a combinaciones de valores. ¿Qué más?

1. Datos de prueba

Si necesita una gran cantidad de datos, CROSS JOIN lo ayudará. Por ejemplo, tiene una tabla de proveedores y productos. Otra tabla contiene productos que ofrece el proveedor. Si está vacío y necesita datos rápidamente, esto es lo que puede hacer:

SELECT
 P.ProductID
,v.BusinessEntityID AS VendorID
FROM 
Production.Product p
CROSS JOIN Purchasing.Vendor v 

Generó 52.416 registros en mi copia de AdventureWorks . Eso es suficiente para probar aplicaciones y rendimiento. Sin embargo, si presenta su aplicación a los usuarios, use su fuente en lugar de estos datos de nuestro ejemplo.

2. Obtener resultados de combinaciones faltantes

En el artículo anterior, ilustramos el uso de OUTER JOIN para obtener resultados de valores faltantes. Esta vez, usaremos combinaciones que faltan. Intentemos obtener los productos donde la Tienda 294 no ganó dinero.

-- get store 294 ('Professional Sales and Service') list of products without sales orders for January 2014
SELECT DISTINCT
 b.Name AS Product
FROM Sales.Store a
CROSS JOIN Production.Product b
LEFT JOIN (SELECT
	     c.StoreID
	    ,a.ProductID
	    ,SUM(a.LineTotal) AS OrderTotal
	    FROM Sales.SalesOrderDetail a
	    INNER JOIN Sales.SalesOrderHeader b ON a.SalesOrderID = b.SalesOrderID
	    INNER JOIN Sales.Customer c ON b.CustomerID = c.CustomerID
	    WHERE c.StoreID = 294 AND
		   b.OrderDate BETWEEN '01/01/2014' AND '01/31/2014'
	    GROUP BY c.StoreID, a.ProductID) d ON a.BusinessEntityID = d.StoreID 
		                                AND b.ProductID = d.ProductID
WHERE d.OrderTotal IS NULL
AND a.BusinessEntityID = 294
ORDER BY b.Name 

Como puede ver, primero necesitamos todas las combinaciones de productos y tiendas:usamos CROSS JOIN. Luego, necesitamos una lista de productos vendidos para el período de enero de 2014. Finalmente, aplique LEFT JOIN a esa lista y use la cláusula WHERE para obtener solo los productos sin ventas. Luego, obtenemos información sobre productos que no se vendieron.

3. Formar palabras a partir de combinaciones de letras

Si te gustan los juegos de palabras con combinaciones de letras, puedes usar CROSS JOIN con una autounión. Aquí hay una muestra usando 3 letras 'D', 'O' y 'G'.


DECLARE @table TABLE(letter CHAR(1) NOT NULL)

INSERT INTO @table
VALUES ('D'),('O'),('G')

SELECT
 a.letter
,b.letter
,c.letter
FROM @table a
CROSS JOIN @table b
CROSS JOIN @table c
WHERE a.letter + b.letter + c.letter LIKE '%O%'

Un código similar sin la cláusula WHERE generará 27 registros. La cláusula WHERE anterior ayudó a eliminar combinaciones de 3 combinaciones de letras similares como 'DDD' o 'GGG'. A continuación se muestra el resultado.

Por supuesto, dado que no puse mucha inteligencia en la consulta, la mayoría de los resultados no son palabras. Aún así, ayuda en la parte de pensamiento del juego.

4. Sugerencias de comidas

A todos nos encanta la comida, pero puede ser difícil elegir las combinaciones correctas. Al igual que en los conceptos de ejemplo anteriores, aquí se explica cómo obtener posibles combinaciones de comidas:


DECLARE @FoodMenu TABLE(FoodItem VARCHAR(50) NOT NULL, ItemType CHAR(1) NOT NULL)

-- main course
INSERT INTO @FoodMenu
VALUES
('Spaghetti with Meatballs','M'),
('Spaghetti with Fried Chicken','M'),
('Rice with Roasted Chicken','M')

-- side dish
INSERT INTO @FoodMenu
VALUES
('Buttered Corn and Carrots','S'),
('French Fries','S'),
('Vegetable Coleslaw','S')

-- drinks
INSERT INTO @FoodMenu
VALUES
('Orange Juice','D'),
('Pineapple Juice','D'),
('Soda','D')

SELECT
 a.FoodItem AS MainCourse
,b.FoodItem AS SideDish
,c.FoodItem AS Drinks
FROM @FoodMenu a
CROSS JOIN @FoodMenu b
CROSS JOIN @FoodMenu c
WHERE a.ItemType = 'M' AND
b.ItemType = 'S' AND
c.ItemType = 'D' 

El resultado:

Algunos de ellos son deseables. Algunos dicen, '¡olvídalo!' Depende de tu gusto.

5. Selección de diseño de camiseta

Otro posible uso de CROSS JOIN es conseguir combinaciones de diseño para camisetas. Aquí hay un código de muestra:


DECLARE @tshirts TABLE(attributeType CHAR(1) NOT NULL, Attribute VARCHAR(15))

--size
INSERT INTO @tshirts
VALUES
('S','Small'),
('S','Medium'),
('S','Large')

--color
INSERT INTO @tshirts
VALUES
('C','Red'),
('C','Blue'),
('C','Green'),
('C','Black'),
('C','Purple'),
('C','Yellow'),
('C','White')

--design
INSERT INTO @tshirts
VALUES
('D','Plain'),
('D','Printed')

SELECT
 a.Attribute AS Size
,b.Attribute AS Color
,c.Attribute AS Design
FROM @tshirts a
CROSS JOIN @tshirts b
CROSS JOIN @tshirts c
WHERE a.attributeType = 'S' AND
b.attributeType = 'C' AND 
c.attributeType = 'D'

¿Y los resultados? Eche un vistazo a su porción en la Figura 3:

¿Puedes pensar en algunos ejemplos más?

Rendimiento CROSS JOIN de SQL Server

¿Cuál es el truco al usar CROSS JOIN? Por lo que vale, CROSS JOIN puede causar problemas de rendimiento si no tiene cuidado. La parte más aterradora es que forma un producto de 2 conjuntos. Por lo tanto, sin limitar los resultados en una cláusula WHERE, Table1 con 1000 registros CROSS JOIN con Table2 con 1.000.000 registros se convertirá en 1.000.000.000 registros. En consecuencia, son muchas páginas para leer con SQL Server.

Como ejemplo, considere emparejar empleados masculinos y femeninos en AdventureWorks .

USE AdventureWorks
GO

SELECT
 P.LastName + ISNULL(' ' + p.Suffix,'') + ', ' + P.FirstName + ISNULL(' ' + P.MiddleName,'') AS Male
,P1.LastName + ISNULL(' ' + p1.Suffix,'') + ', ' + P1.FirstName + ISNULL(' ' + P1.MiddleName,'') AS Female
FROM HumanResources.Employee e
INNER JOIN Person.Person p ON e.BusinessEntityID = P.BusinessEntityID
CROSS JOIN HumanResources.Employee e1
INNER JOIN Person.Person p1 ON e1.BusinessEntityID = p1.BusinessEntityID
WHERE e.Gender = 'M'
AND e1.Gender = 'F' 

El código anterior le brinda todos los pares posibles de empleados masculinos y femeninos. Obtuve solo 17 304 registros, pero mire las lecturas lógicas en la Figura 4:

¿Viste las lecturas lógicas de la Persona? ¿mesa? ¡Eso es leer páginas de 53,268 x 8KB! Sin mencionar la WorkTable las lecturas lógicas se realizan en tempdb .

¿La conclusión? Verifique STATISTICS IO, y si le molesta ver grandes lecturas lógicas, exprese una consulta de manera diferente. Las condiciones adicionales en la cláusula WHERE o un enfoque de divide y vencerás pueden ayudar.

Cuando una CROSS JOIN se convierte en una INNER JOIN

Sí, eso es correcto. SQL Server puede procesar CROSS JOIN como INNER JOIN. Mencionamos antes que cuando un RIGHT JOIN se procesa como LEFT JOIN, puede aplicarse a CROSS JOIN. Echa un vistazo al siguiente código:

SELECT
 c.CustomerID
,c.AccountNumber
,P.BusinessEntityID
,P.LastName
,P.FirstName
FROM Sales.Customer c
CROSS JOIN Person.Person p
WHERE c.PersonID = P.BusinessEntityID 

Antes de revisar el Plan de Ejecución, tengamos el equivalente de INNER JOIN.

SELECT
 c.CustomerID
,c.AccountNumber
,P.BusinessEntityID
,P.LastName
,P.FirstName
FROM Sales.Customer c
INNER JOIN Person.Person p ON c.PersonID = P.BusinessEntityID 

Ahora, revisa el Plan de Ejecución a continuación.

El plan superior es la consulta mediante CROSS JOIN. El plan inferior es la consulta mediante un INNER JOIN. Tienen el mismo QueryHashPlan .

¿Notaste la coincidencia hash? operador del plan superior? Es una UNIÓN INTERNA. Pero usamos un CROSS JOIN en el código. La cláusula WHERE en la primera consulta (WHERE c.PersonID =P.BusinessEntityID ) obligaron a los resultados a tener combinaciones solo con claves iguales. Entonces, lógicamente es una UNIÓN INTERNA.

¿Cuál es mejor? Es su elección personal. Prefiero INNER JOIN porque la intención es unir 2 tablas con claves iguales. El uso de INNER JOIN lo deja muy claro. Pero así soy yo.

Conclusión

CROSS JOIN es bueno para darle todas las combinaciones de valores posibles. Sin embargo, se le advirtió que puede causar algún tipo de "explosión" de datos. Use este ÚNETE con cuidado. Limite los resultados tanto como pueda. Además, puede escribir un CROSS JOIN que sea funcionalmente equivalente a INNER JOIN.

Este artículo finaliza la serie sobre SQL JOIN. Para futuras referencias, puede marcar este artículo como favorito. O añádelo a tu colección en un navegador.

¿Y no olvides compartir este artículo en tus redes sociales favoritas?