CROSS JOIN è sotto i riflettori. Questo articolo conclude la nostra piccola serie di pubblicazioni relative a SQL JOIN. Se ti sei perso i due articoli precedenti, consultali come segue:
- La tua guida definitiva all'unione SQL – Parte 1:INNER JOIN
- La tua guida definitiva all'unione SQL – Parte 2:OUTER JOIN
SQL Server CROSS JOIN è il più semplice di tutti i join. Implementa una combinazione di 2 tabelle senza una condizione di join. Se hai 5 righe in una tabella e 3 righe in un'altra, ottieni 15 combinazioni. Altra definizione è Prodotto cartesiano.
Ora, perché vorresti combinare le tabelle senza una condizione di join? Aspetta un po' perché ci stiamo arrivando. Per prima cosa, facciamo riferimento alla sintassi.
Sintassi SQL CROSS JOIN
Come con INNER JOIN, puoi avere un CROSS JOIN da 2 standard, SQL-92 e SQL-89. T-SQL supporta entrambe le sintassi, ma preferisco SQL-92. Controlla la parte 1 dedicata a INNER JOIN se vuoi sapere perché.
Sintassi 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
Proprio come SQL-89 – INNER JOIN senza la condizione di join.
5 esempi di utilizzo di SQL Server CROSS JOIN
Potresti chiederti quando puoi usare SQL CROSS JOIN. Naturalmente, è utile per dare forma a combinazioni di valori. Cos'altro?
1. Dati di prova
Se hai bisogno di una grande quantità di dati, un CROSS JOIN ti aiuterà. Ad esempio, hai una tabella di fornitori e prodotti. Un'altra tabella contiene i prodotti offerti dal fornitore. Se è vuoto e hai bisogno di dati velocemente, ecco cosa puoi fare:
SELECT
P.ProductID
,v.BusinessEntityID AS VendorID
FROM
Production.Product p
CROSS JOIN Purchasing.Vendor v
Ha generato 52.416 record nella mia copia di AdventureWorks . È sufficiente per testare app e prestazioni. Tuttavia, se presenti la tua app agli utenti, utilizza la tua fonte invece di questi dati dal nostro esempio.
2. Ottenere risultati dalle combinazioni mancanti
Nell'articolo precedente, abbiamo illustrato l'utilizzo di OUTER JOIN per ottenere risultati dai valori mancanti. Questa volta useremo le combinazioni mancanti. Proviamo a ottenere i prodotti in cui Store 294 non ha fatto soldi.
-- 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
Come puoi vedere, per prima cosa abbiamo bisogno di tutte le combinazioni di prodotti e negozi:utilizziamo un CROSS JOIN. Quindi, abbiamo bisogno di un elenco di prodotti venduti per il periodo di gennaio 2014. Infine, applica LEFT JOIN a tale elenco e utilizza la clausola WHERE per ottenere solo i prodotti senza vendite. Quindi, riceviamo informazioni sui prodotti che non sono stati venduti.
3. Formare parole da combinazioni di lettere
Se ti piacciono i giochi di parole con le combinazioni di lettere, puoi usare CROSS JOIN con un self-join. Ecco un esempio che utilizza 3 lettere "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%'
Un codice simile senza la clausola WHERE genererà 27 record. La clausola WHERE sopra ha aiutato a eliminare le combinazioni di 3 combinazioni di lettere simili come "DDD" o "GGG". Di seguito il risultato.
Naturalmente, dal momento che non ho messo molta intelligenza nella query, la maggior parte dei risultati sono non parole. Tuttavia, aiuta nella parte pensante del gioco.
4. Suggerimenti per i pasti
Tutti amiamo il cibo, ma può essere difficile scegliere le giuste combinazioni. Come nei precedenti concetti di esempio, ecco come ottenere possibili combinazioni di pasti:
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'
Il risultato:
Alcuni di loro sono desiderabili. Alcuni sono tipo "dimenticalo!" Dipende dai tuoi gusti.
5. Selezione di design per magliette
Un altro possibile utilizzo di CROSS JOIN è ottenere combinazioni di design per camicie. Ecco un codice di esempio:
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 i risultati? Dai un'occhiata alla sua porzione nella Figura 3:
Ti vengono in mente altri esempi?
Prestazioni CROSS JOIN di SQL Server
Qual è il problema nell'usare CROSS JOIN? Per quel che vale, CROSS JOIN può causare problemi di prestazioni se non stai attento. La parte più spaventosa è che forma un prodotto di 2 set. Pertanto, senza limitare i risultati in una clausola WHERE, Tabella1 con 1000 record CROSS JOIN con Table2 con 1.000.000 di record diventeranno 1.000.000.000 di record. Di conseguenza, sono molte le pagine da leggere da SQL Server.
Ad esempio, considera l'abbinamento di dipendenti maschi e femmine in 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'
Il codice sopra fornisce tutte le possibili coppie di dipendenti maschi e femmine. Ho ottenuto solo 17.304 record, ma guarda le letture logiche nella Figura 4:
Hai visto le letture logiche della Persona tavolo? Sta leggendo 53.268 x 8 KB di pagine! Per non parlare del WorkTable le letture logiche vengono eseguite in tempdb .
La conclusione? Controlla STATISTICS IO e, se ti dà fastidio vedere grandi letture logiche, esprimi una query in modo diverso. Condizioni aggiuntive nella clausola WHERE o un approccio divide et impera possono aiutare.
Quando un CROSS JOIN diventa un INNER JOIN
Sì, è giusto. SQL Server può elaborare un CROSS JOIN come INNER JOIN. Abbiamo accennato in precedenza che quando un RIGHT JOIN viene elaborato come LEFT JOIN, può essere applicato a CROSS JOIN. Dai un'occhiata al codice qui sotto:
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
Prima di controllare il piano di esecuzione, disponiamo dell'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
Ora, controlla il piano di esecuzione di seguito.
Il piano superiore è la query che utilizza un CROSS JOIN. Il piano inferiore è la query che utilizza un INNER JOIN. Hanno lo stesso QueryHashPlan .
Hai notato la Corrispondenza hash operatore del piano superiore? È un'UNIONE INTERIORE. Ma abbiamo usato un CROSS JOIN nel codice. La clausola WHERE nella prima query (WHERE c.PersonID =P.BusinessEntityID ) ha costretto i risultati ad avere combinazioni solo con chiavi uguali. Quindi, logicamente è un INNER JOIN.
Qual è il migliore? È una tua scelta personale. Preferisco INNER JOIN perché l'intento è quello di unire 2 tabelle con chiavi uguali. L'uso di INNER JOIN lo rende molto chiaro. Ma sono solo io.
Conclusione
CROSS JOIN è buono per darti tutte le possibili combinazioni di valore. Sei stato avvertito, tuttavia, che può causare una sorta di "esplosione" dei dati. Usa questo JIN con attenzione. Limita i risultati il più possibile. Inoltre, puoi scrivere un CROSS JOIN che è funzionalmente equivalente a INNER JOIN.
Questo articolo conclude la serie sugli SQL JOIN. Per riferimenti futuri, puoi aggiungere questo articolo ai segnalibri. Oppure aggiungilo alla tua raccolta in un browser.
E non dimenticare di condividere questo articolo sui tuoi social media preferiti?