Database
 sql >> Base de Dados >  >> RDS >> Database

Seu guia definitivo para SQL Join:CROSS JOIN – Parte 3


CROSS JOIN está no centro das atenções. Este artigo conclui nossa pequena série de publicações relacionadas ao SQL JOIN. Se você perdeu os dois artigos anteriores, consulte-os da seguinte forma:
  • Seu guia definitivo para SQL Join – Parte 1:INNER JOIN
  • Seu guia definitivo para SQL Join – Parte 2:OUTER JOIN

SQL Server CROSS JOIN é a mais simples de todas as junções. Ele implementa uma combinação de 2 tabelas sem uma condição de junção. Se você tiver 5 linhas em uma tabela e 3 linhas em outra, terá 15 combinações. Outra definição é um produto cartesiano.

Agora, por que você deseja combinar tabelas sem uma condição de junção? Espere um pouco porque estamos chegando lá. Primeiro, vamos nos referir à sintaxe.

Sintaxe SQL CROSS JOIN


Assim como no INNER JOIN, você pode ter um CROSS JOIN de 2 padrões, SQL-92 e SQL-89. T-SQL suporta ambas as sintaxes, mas prefiro SQL-92. Verifique a parte 1 dedicada ao INNER JOIN se quiser saber o porquê.

Sintaxe 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 

Muito parecido com SQL-89 – INNER JOIN sem a condição de junção.

5 exemplos de uso do SQL Server CROSS JOIN


Você pode se perguntar quando pode usar SQL CROSS JOIN. Claro, é útil para moldar combinações de valor. O quê mais?

1. Dados de teste


Se você precisar de uma grande quantidade de dados, um CROSS JOIN irá ajudá-lo. Por exemplo, você tem uma tabela de fornecedores e produtos. Outra tabela contém produtos que o fornecedor oferece. Se estiver vazio e você precisar de dados rapidamente, veja o que você pode fazer:
SELECT
 P.ProductID
,v.BusinessEntityID AS VendorID
FROM 
Production.Product p
CROSS JOIN Purchasing.Vendor v 

Gerou 52.416 registros em minha cópia do AdventureWorks . Isso é suficiente para testar aplicativos e desempenho. No entanto, se você apresentar seu aplicativo aos usuários, use sua fonte em vez desses dados do nosso exemplo.

2. Obtendo resultados de combinações ausentes


No artigo anterior, ilustramos o uso do OUTER JOIN para obter resultados de valores ausentes. Desta vez, usaremos combinações ausentes. Vamos tentar obter os produtos onde a Loja 294 não rendeu dinheiro.
-- 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 você pode ver, primeiro precisamos de todas as combinações de produtos e lojas – usamos um CROSS JOIN. Então, precisamos de uma lista de produtos vendidos para o período de janeiro de 2014. Por fim, aplique LEFT JOIN a essa lista e use a cláusula WHERE para obter apenas os produtos sem vendas. Em seguida, obtemos informações sobre produtos que não foram vendidos.

3. Formando palavras a partir de combinações de letras


Se você gosta de jogos de palavras com combinações de letras, pode usar CROSS JOIN com uma junção automática. Aqui está uma amostra usando 3 letras 'D', 'O' e '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%'

Um código semelhante sem a cláusula WHERE gerará 27 registros. A cláusula WHERE acima ajudou a eliminar combinações de 3 combinações de letras semelhantes, como 'DDD' ou 'GGG'. Abaixo está o resultado.

Claro, como não coloquei muita inteligência na consulta, a maioria dos resultados são não-palavras. Ainda assim, ajuda na parte de pensamento do jogo.

4. Sugestões de refeições


Todos nós adoramos comida, mas pode ser difícil escolher as combinações certas. Como nos conceitos de exemplo anteriores, aqui está como obter possíveis combinações de refeições:

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' 

O resultado:

Alguns deles são desejáveis. Alguns são como, 'esqueça!' Depende do seu gosto.

5. Seleção de design de camiseta


Outro uso possível do CROSS JOIN é obter combinações de design para camisas. Aqui está um código de exemplo:

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'

E os resultados? Dê uma olhada em sua parte na Figura 3:

Você consegue pensar em mais alguns exemplos?

Desempenho de CROSS JOIN do SQL Server


Qual é o problema em usar CROSS JOIN? Vale a pena, CROSS JOIN pode causar problemas de desempenho se você não for cuidadoso. A parte mais assustadora é que forma um produto de 2 conjuntos. Assim, sem limitar os resultados em uma cláusula WHERE, Tabela1 com 1000 registros CROSS JOIN com Tabela2 com 1.000.000 de registros se tornará 1.000.000.000 de registros. Consequentemente, são muitas páginas para serem lidas pelo SQL Server.

Como exemplo, considere emparelhar funcionários do sexo masculino e feminino na 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' 

O código acima fornece todos os pares possíveis de funcionários masculinos e femininos. Eu tenho apenas 17.304 registros, mas veja as leituras lógicas na Figura 4:

Você viu as leituras lógicas da Pessoa tabela? Isso é ler 53.268 páginas de 8 KB! Sem mencionar a WorkTable leituras lógicas são feitas em tempdb .

A conclusão? Verifique o STATISTICS IO e, se incomoda você ver grandes leituras lógicas, expresse uma consulta de maneira diferente. Condições adicionais na cláusula WHERE ou uma abordagem de divisão e conquista podem ajudar.

Quando um CROSS JOIN se torna um INNER JOIN


Sim está certo. O SQL Server pode processar um CROSS JOIN como um INNER JOIN. Mencionamos antes que quando um RIGHT JOIN é processado como LEFT JOIN, ele pode ser aplicado a CROSS JOIN. Dê uma olhada no código abaixo:
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 verificarmos o Plano de Execução, vamos ter o equivalente 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 

Agora, verifique o Plano de Execução abaixo.

O plano superior é a consulta usando um CROSS JOIN. O plano inferior é a consulta usando um INNER JOIN. Eles têm o mesmo QueryHashPlan .

Você notou a Correspondência de hash operadora do plano superior? É um INNER JOIN. Mas usamos um CROSS JOIN no código. A cláusula WHERE na primeira consulta (WHERE c.PersonID =P.BusinessEntityID ) forçou os resultados a terem combinações apenas com chaves iguais. Então, logicamente é um INNER JOIN.

Qual é o melhor? É sua escolha pessoal. Eu prefiro INNER JOIN porque a intenção é juntar 2 tabelas com chaves iguais. Usar INNER JOIN deixa isso muito claro. Mas isso sou só eu.

Conclusão


CROSS JOIN é bom para fornecer todas as combinações de valor possíveis. Você foi avisado, no entanto, que isso pode causar algum tipo de “explosão” de dados. Use este JOIN com cuidado. Limite os resultados o máximo que puder. Além disso, você pode escrever um CROSS JOIN que seja funcionalmente equivalente ao INNER JOIN.

Este artigo encerra a série sobre SQL JOINs. Para referências futuras, você pode marcar este artigo. Ou adicione-o à sua coleção em um navegador.

E não se esqueça de compartilhar este artigo em suas redes sociais favoritas?