sql >> Database teknologi >  >> RDS >> Database

Din ultimative guide til SQL Join:CROSS JOIN – Del 3

CROSS JOIN er i søgelyset. Denne artikel afslutter vores lille serie af SQL JOIN-relaterede publikationer. Hvis du gik glip af de to foregående artikler, skal du henvise til dem som følger:

  • Din ultimative guide til SQL Join – Del 1:INNER JOIN
  • Din ultimative guide til SQL Join – Del 2:OUTER JOIN

SQL Server CROSS JOIN er den enkleste af alle joinforbindelser. Den implementerer en kombination af 2 borde uden en sammenføjningsbetingelse. Hvis du har 5 rækker i en tabel og 3 rækker i en anden, får du 15 kombinationer. En anden definition er et kartesisk produkt.

Hvorfor vil du nu kombinere borde uden en sammenføjningsbetingelse? Vent lidt, for vi er ved at nå dertil. Lad os først henvise til syntaksen.

SQL CROSS JOIN-syntaks

Ligesom med INNER JOIN, kan du have en CROSS JOIN fra 2 standarder, SQL-92 og SQL-89. T-SQL understøtter begge syntakser, men jeg foretrækker SQL-92. Tjek del 1 dedikeret til INNER JOIN, hvis du vil vide hvorfor.

SQL-92-syntaks

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

SQL-89

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

Meget gerne SQL-89 – INNER JOIN uden join-betingelsen.

5 eksempler på brug af SQL Server CROSS JOIN

Du spekulerer måske på, hvornår du kan bruge SQL CROSS JOIN. Selvfølgelig er det nyttigt til at forme værdikombinationer. Hvad ellers?

1. Testdata

Hvis du har brug for en stor mængde data, vil en CROSS JOIN hjælpe dig. For eksempel har du en tabel over leverandører og produkter. En anden tabel indeholder produkter, som sælgeren tilbyder. Hvis den er tom, og du hurtigt har brug for data, kan du gøre følgende:

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

Det genererede 52.416 poster i min kopi af AdventureWorks . Det er nok til at teste apps og ydeevne. Men hvis du præsenterer din app for brugerne, skal du bruge din kilde i stedet for disse data fra vores eksempel.

2. Få resultater fra manglende kombinationer

I den forrige artikel illustrerede vi brugen af ​​OUTER JOIN til at få resultater fra manglende værdier. Denne gang vil vi bruge manglende kombinationer. Lad os prøve at få de produkter, hvor Store 294 ikke tjente penge.

-- 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 kan se, skal vi først have alle produkt- og butikskombinationer – vi bruger en CROSS JOIN. Så har vi brug for en liste over solgte produkter for januar 2014-perioden. Til sidst skal du anvende LEFT JOIN på listen og bruge WHERE-klausulen til kun at få produkterne uden salg. Så får vi information om produkter, der ikke blev solgt.

3. Dannelse af ord ud fra bogstavkombinationer

Hvis du er til ordspil med bogstavkombinationer, kan du bruge CROSS JOIN med en selvtilslutning. Her er et eksempel med 3 bogstaver "D", "O" og "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 lignende kode uden WHERE-sætningen vil generere 27 poster. WHERE-sætningen ovenfor hjalp med at eliminere kombinationer af 3 lignende bogstavkombinationer som "DDD" eller "GGG". Nedenfor er resultatet.

Selvfølgelig, da jeg ikke lagde meget intelligens i forespørgslen, er de fleste af resultaterne ikke-ord. Alligevel hjælper det i den tænkende del af spillet.

4. Måltidsforslag

Vi elsker alle mad, men det kan være svært at vælge de rigtige kombinationer. Som i de foregående eksempelkoncepter er her, hvordan du får mulige 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:

Nogle af dem er ønskværdige. Nogle er ligesom, 'glem det!' Det afhænger af din smag.

5. T-shirt design udvalg

En anden mulig anvendelse af CROSS JOIN er at få designkombinationer til skjorter. Her er en prøvekode:


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'

Og resultaterne? Tag et kig på dens del i figur 3:

Kan du komme i tanke om nogle flere eksempler?

SQL Server CROSS JOIN Ydeevne

Hvad er fangsten ved at bruge CROSS JOIN? For hvad det er værd, kan CROSS JOIN forårsage præstationsproblemer, hvis du ikke er forsigtig. Det mest skræmmende er, at det danner et produkt af 2 sæt. Uden at begrænse resultaterne i en WHERE-sætning, Tabel1 med 1000 poster CROSS JOIN med Tabel2 med 1.000.000 poster bliver til 1.000.000.000 poster. Derfor er det mange sider, der skal læses af SQL Server.

Som et eksempel kan du overveje at parre mandlige og kvindelige medarbejdere 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' 

Ovenstående kode giver dig alle mulige par af mandlige og kvindelige medarbejdere. Jeg fik kun 17.304 poster, men se på de logiske læsninger i figur 4:

Så du de logiske læsninger af Personen bord? Det er 53.268 x 8KB sider! For ikke at nævne Arbejdstabellen logiske læsninger udføres i tempdb .

Konklusionen? Tjek STATISTICS IO, og hvis det forstyrrer dig at se store logiske læsninger, så udtryk en forespørgsel anderledes. Yderligere betingelser i WHERE-klausulen eller en del-og-hersk tilgang kan hjælpe.

Når en CROSS JOIN bliver en INNER JOIN

Ja det er rigtigt. SQL Server kan behandle en CROSS JOIN som en INNER JOIN. Vi nævnte før, at når en RIGHT JOIN behandles som en LEFT JOIN, kan den gælde for CROSS JOIN. Tag et kig på koden nedenfor:

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 

Inden vi tjekker udførelsesplanen, lad os få den tilsvarende 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 

Tjek nu udførelsesplanen nedenfor.

Den øverste plan er forespørgslen ved hjælp af en CROSS JOIN. Den nederste plan er forespørgslen ved hjælp af en INNER JOIN. De har den samme QueryHashPlan .

Har du bemærket Hash Match operatør af topplanen? Det er en INDRE JOIN. Men vi brugte en CROSS JOIN i kode. WHERE-sætningen i den første forespørgsel (WHERE c.PersonID =P.BusinessEntityID ) tvang resultaterne til kun at have kombinationer med lige store taster. Så logisk set er det en INNER JOIN.

Hvilken er bedst? Det er dit personlige valg. Jeg foretrækker INNER JOIN, fordi hensigten er at samle 2 borde med lige store nøgler. Brug af INNER JOIN gør det meget tydeligt. Men det er bare mig.

Konklusion

CROSS JOIN er god til at give dig alle mulige værdikombinationer. Du er dog blevet advaret om, at det kan forårsage en form for data "eksplosion". Brug denne JOIN omhyggeligt. Begræns resultaterne så meget som muligt. Du kan også skrive en CROSS JOIN, der funktionelt svarer til INNER JOIN.

Denne artikel afslutter serien om SQL JOINs. For fremtidige referencer kan du bogmærke denne artikel. Eller føj det til din samling i en browser.

Og glem ikke at dele denne artikel på dine foretrukne sociale medier?


  1. Find og fjern ikke-ASCII-tegn fra en Oracle Varchar2

  2. RAWTOHEX() Funktion i Oracle

  3. Indstilling af Active Data Guard Physical Standby i RAC One Node Architecture – Del 2

  4. Revision i Oracle