sql >> Databasteknik >  >> RDS >> Database

Din ultimata guide till SQL Join:CROSS JOIN – Del 3

CROSS JOIN är i rampljuset. Den här artikeln avslutar vår lilla serie av SQL JOIN-relaterade publikationer. Om du missade de två föregående artiklarna, hänvisa till dem enligt följande:

  • Din ultimata guide till SQL Join – Del 1:INNER JOIN
  • Din ultimata guide till SQL Join – Del 2:OUTER JOIN

SQL Server CROSS JOIN är den enklaste av alla kopplingar. Den implementerar en kombination av 2 tabeller utan ett sammanfogningsvillkor. Om du har 5 rader i en tabell och 3 rader i en annan får du 15 kombinationer. En annan definition är en kartesisk produkt.

Varför skulle du nu vilja kombinera tabeller utan ett sammanfogningsvillkor? Vänta lite för vi närmar oss. Låt oss först hänvisa till syntaxen.

SQL CROSS JOIN-syntax

Precis som med INNER JOIN kan du ha en CROSS JOIN från 2 standarder, SQL-92 och SQL-89. T-SQL stöder båda syntaxerna, men jag föredrar SQL-92. Kolla del 1 tillägnad INNER JOIN om du vill veta varför.

SQL-92-syntax

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

SQL-89

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

Ungefär som SQL-89 – INNER JOIN utan joinvillkoret.

5 exempel på användning av SQL Server CROSS JOIN

Du kanske undrar när du kan använda SQL CROSS JOIN. Naturligtvis är det användbart för att forma värdekombinationer. Vad mer?

1. Testdata

Om du behöver en stor mängd data hjälper en CROSS JOIN dig. Till exempel har du en tabell över leverantörer och produkter. En annan tabell innehåller produkter som leverantören erbjuder. Om det är tomt och du behöver data snabbt kan du göra det här:

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

Det genererade 52 416 poster i mitt exemplar av AdventureWorks . Det räcker för att testa appar och prestanda. Men om du presenterar din app för användare, använd din källa istället för denna data från vårt exempel.

2. Få resultat från saknade kombinationer

I den föregående artikeln illustrerade vi användningen av OUTER JOIN för att få resultat från saknade värden. Den här gången kommer vi att använda saknade kombinationer. Låt oss försöka få tag på produkterna där Store 294 inte tjänade pengar.

-- 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 

Som du ser behöver vi först alla produkt- och butikskombinationer – vi använder en CROSS JOIN. Sedan behöver vi en lista över sålda produkter för perioden januari 2014. Till sist, använd LEFT JOIN på den listan och använd WHERE-klausulen för att bara få produkter utan försäljning. Sedan får vi information om produkter som inte sålts.

3. Forma ord från bokstavskombinationer

Om du gillar ordspel med bokstavskombinationer kan du använda CROSS JOIN med en självanslutning. Här är ett exempel med tre bokstäver "D", "O" och "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%'

En liknande kod utan WHERE-satsen kommer att generera 27 poster. WHERE-satsen ovan hjälpte till att eliminera kombinationer av tre liknande bokstavskombinationer som "DDD" eller "GGG". Nedan är resultatet.

Naturligtvis, eftersom jag inte lagt ner mycket intelligens i frågan, är de flesta av resultaten icke-ord. Ändå hjälper det i den tänkande delen av spelet.

4. Måltidsförslag

Vi älskar alla mat, men det kan vara svårt att välja rätt kombinationer. Som i de tidigare exempelkoncepten, så här får du möjliga måltidskombinationer:


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' 

Resultatet:

Några av dem är önskvärda. Vissa säger "glöm det!" Det beror på din smak.

5. Val av t-shirtdesign

En annan möjlig användning av CROSS JOIN är att få designkombinationer för skjortor. Här är en exempelkod:


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'

Och resultaten? Ta en titt på dess del i figur 3:

Kan du komma på några fler exempel?

SQL Server CROSS JOIN-prestanda

Vad är haken med att använda CROSS JOIN? För vad det är värt kan CROSS JOIN orsaka prestandaproblem om du inte är försiktig. Det läskigaste är att det bildar en produkt av 2 set. Utan begränsning resulterar alltså i en WHERE-sats, Tabell1 med 1000 poster CROSS JOIN med Tabell2 med 1 000 000 poster blir 1 000 000 000 poster. Följaktligen är det många sidor att läsa av SQL Server.

Som ett exempel, överväg att para ihop manliga och kvinnliga anställda i 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' 

Ovanstående kod ger dig alla möjliga par av manliga och kvinnliga anställda. Jag fick bara 17 304 poster, men titta på de logiska läsningarna i figur 4:

Såg du de logiska läsningarna av Personen tabell? Det är 53 268 x 8KB sidor! För att inte tala om Arbetstabellen logiska läsningar görs i tempdb .

Slutsatsen? Kontrollera STATISTICS IO, och om det besvärar dig att se stora logiska läsningar, uttryck en fråga annorlunda. Ytterligare villkor i WHERE-klausulen eller en dela-och-härska-strategi kan hjälpa.

När en CROSS JOIN blir en INNER JOIN

Ja det stämmer. SQL Server kan behandla en CROSS JOIN som en INNER JOIN. Vi nämnde tidigare att när en RIGHT JOIN behandlas som en LEFT JOIN kan den gälla CROSS JOIN. Ta en titt på koden nedan:

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 

Innan vi kollar in exekveringsplanen, låt oss ha motsvarande 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 

Kontrollera nu genomförandeplanen nedan.

Den översta planen är frågan som använder en CROSS JOIN. Den nedersta planen är frågan som använder en INNER JOIN. De har samma QueryHashPlan .

Lade du märke till Hash Match operatör av toppplanen? Det är en INRE JOIN. Men vi använde en CROSS JOIN i kod. WHERE-satsen i den första frågan (WHERE c.PersonID =P.BusinessEntityID ) tvingade resultaten att endast ha kombinationer med lika nycklar. Så logiskt sett är det en INNER JOIN.

Vilken är bättre? Det är ditt personliga val. Jag föredrar INNER JOIN eftersom avsikten är att sammanfoga 2 bord med lika nycklar. Att använda INNER JOIN gör det väldigt tydligt. Men det är bara jag.

Slutsats

CROSS JOIN är bra för att ge dig alla möjliga värdekombinationer. Du har dock blivit varnad för att det kan orsaka någon form av dataexplosion. Använd denna JOIN försiktigt. Begränsa resultaten så mycket du kan. Du kan också skriva en CROSS JOIN som är funktionellt likvärdig med INNER JOIN.

Den här artikeln avslutar serien om SQL JOINs. För framtida referenser kan du bokmärka den här artikeln. Eller lägg till den i din samling i en webbläsare.

Och glöm inte att dela den här artikeln på dina favorit sociala medier?


  1. Oracle Shutdown-fel ORA-01033

  2. Hur gör man två frågor med vanliga kolumner (A, B) och (A, C) till bara en (A, B, C)?

  3. Hur REGEXP_SUBSTR()-funktionen fungerar i MySQL

  4. Ansluta Talend på Windows till en ODBC-databas