sql >> Database >  >> RDS >> Database

Uw ultieme gids voor SQL Join:CROSS JOIN - Deel 3

CROSS JOIN staat in de schijnwerpers. Dit artikel voltooit onze kleine reeks van SQL JOIN-gerelateerde publicaties. Als je de vorige twee artikelen hebt gemist, raadpleeg ze dan als volgt:

  • Uw ultieme gids voor SQL Join - Deel 1:INNER JOIN
  • Uw ultieme gids voor SQL Join - Deel 2:OUTER JOIN

SQL Server CROSS JOIN is de eenvoudigste van alle joins. Het implementeert een combinatie van 2 tabellen zonder een join-voorwaarde. Als je 5 rijen in de ene tabel hebt en 3 rijen in een andere, krijg je 15 combinaties. Een andere definitie is een cartesiaans product.

Waarom zou je tabellen willen combineren zonder een join-voorwaarde? Nog even geduld want we komen er aan. Laten we eerst naar de syntaxis verwijzen.

SQL CROSS JOIN-syntaxis

Net als bij INNER JOIN kun je een CROSS JOIN hebben van 2 standaarden, SQL-92 en SQL-89. T-SQL ondersteunt beide syntaxis, maar ik geef de voorkeur aan SQL-92. Check deel 1 gewijd aan INNER JOIN als je wilt weten waarom.

SQL-92-syntaxis

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

SQL-89

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

Net zoals SQL-89 – INNER JOIN zonder de join-voorwaarde.

5 voorbeelden van het gebruik van SQL Server CROSS JOIN

U vraagt ​​zich misschien af ​​wanneer u SQL CROSS JOIN kunt gebruiken. Het is natuurlijk handig om waardecombinaties vorm te geven. Wat nog meer?

1. Testgegevens

Als je een grote hoeveelheid data nodig hebt, kan een CROSS JOIN je helpen. U hebt bijvoorbeeld een tabel met leveranciers en producten. Een andere tabel bevat producten die de verkoper aanbiedt. Als het leeg is en u snel gegevens nodig heeft, kunt u het volgende doen:

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

Het genereerde 52.416 records in mijn exemplaar van AdventureWorks . Dat is genoeg om apps en prestaties te testen. Als u uw app echter aan gebruikers presenteert, gebruik dan uw bron in plaats van deze gegevens uit ons voorbeeld.

2. Resultaten halen uit ontbrekende combinaties

In het vorige artikel hebben we het gebruik van de OUTER JOIN geïllustreerd voor het verkrijgen van resultaten van ontbrekende waarden. Deze keer gebruiken we ontbrekende combinaties. Laten we proberen de producten te krijgen waar Store 294 geen geld aan verdiende.

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

Zoals je ziet hebben we eerst alle product- en winkelcombinaties nodig – we gebruiken een CROSS JOIN. Vervolgens hebben we een lijst nodig met producten die zijn verkocht voor de periode van januari 2014. Pas ten slotte LEFT JOIN toe op die lijst en gebruik de WHERE-clausule om alleen de producten zonder verkoop te krijgen. Vervolgens krijgen we informatie over producten die niet zijn verkocht.

3. Woorden vormen uit lettercombinaties

Als je van woordspelletjes met lettercombinaties houdt, kun je CROSS JOIN gebruiken met een self-join. Hier is een voorbeeld met 3 letters 'D', 'O' en '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%'

Een vergelijkbare code zonder de WHERE-clausule zal 27 records genereren. De WHERE-clausule hierboven hielp combinaties van 3 vergelijkbare lettercombinaties zoals 'DDD' of 'GGG' te elimineren. Hieronder is het resultaat.

Omdat ik niet veel intelligentie in de zoekopdracht heb gestopt, zijn de meeste resultaten natuurlijk niet-woorden. Toch helpt het in het denkgedeelte van het spel.

4. Maaltijdsuggesties

We houden allemaal van eten, maar het kan moeilijk zijn om de juiste combinaties te kiezen. Net als in de vorige voorbeeldconcepten, kunt u als volgt mogelijke maaltijdcombinaties krijgen:


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' 

Het resultaat:

Sommige zijn wenselijk. Sommige zijn als, 'vergeet het maar!' Het hangt af van je smaak.

5. Selectie T-shirtontwerp

Een ander mogelijk gebruik van CROSS JOIN is het verkrijgen van ontwerpcombinaties voor overhemden. Hier is een voorbeeldcode:


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'

En de resultaten? Bekijk het deel ervan in figuur 3:

Kun je nog meer voorbeelden bedenken?

SQL Server CROSS JOIN-prestaties

Wat is het voordeel van het gebruik van CROSS JOIN? Voor wat het waard is, CROSS JOIN kan prestatieproblemen veroorzaken als je niet voorzichtig bent. Het engste is, het vormt een product van 2 sets. Dus, zonder beperking van de resultaten in een WHERE-clausule, Tabel1 met 1000 records CROSS JOIN met Tabel2 met 1.000.000 records worden 1.000.000.000 records. Dat zijn dus veel pagina's om te lezen door SQL Server.

Overweeg bijvoorbeeld om mannelijke en vrouwelijke werknemers te koppelen 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' 

Bovenstaande code geeft u alle mogelijke paren van mannelijke en vrouwelijke werknemers. Ik heb slechts 17.304 records, maar kijk naar de logische waarden in figuur 4:

Heb je de logische waarden van de Persoon . gezien? tafel? Dat is 53.268 x 8KB pagina's lezen! Om nog maar te zwijgen over de WorkTable logische uitlezingen worden gedaan in tempdb .

De conclusie? Controleer de STATISTICS IO, en als u problemen ondervindt bij het zien van grote logische waarden, kunt u een vraag anders uitdrukken. Aanvullende voorwaarden in de WHERE-clausule of een verdeel-en-heers-aanpak kunnen helpen.

Als een CROSS JOIN een INNER JOIN wordt

Ja dat klopt. SQL Server kan een CROSS JOIN verwerken als een INNER JOIN. We hebben eerder vermeld dat wanneer een RIGHT JOIN wordt verwerkt als een LEFT JOIN, deze van toepassing kan zijn op CROSS JOIN. Bekijk de onderstaande code:

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 

Laten we, voordat we het Uitvoeringsplan bekijken, het INNER JOIN-equivalent hebben.

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 

Bekijk nu het Uitvoeringsplan hieronder.

Het bovenste plan is de query met behulp van een CROSS JOIN. Het onderste plan is de query met behulp van een INNER JOIN. Ze hebben hetzelfde QueryHashPlan .

Heb je de Hash Match . opgemerkt? exploitant van het topplan? Het is een INNERLIJKE JOIN. Maar we gebruikten een CROSS JOIN in code. De WHERE-component in de eerste query (WHERE c.PersonID =P.BusinessEntityID ) dwong de resultaten om alleen combinaties met gelijke sleutels te hebben. Dus logischerwijs is het een INNER JOIN.

Welke is beter? Het is uw persoonlijke keuze. Ik geef de voorkeur aan INNER JOIN omdat het de bedoeling is om 2 tabellen met gelijke sleutels samen te voegen. Het gebruik van INNER JOIN maakt het heel duidelijk. Maar dat ben ik.

Conclusie

CROSS JOIN is goed om je alle mogelijke waardecombinaties te geven. U bent echter gewaarschuwd dat het een soort "explosie" van gegevens kan veroorzaken. Gebruik deze JOIN zorgvuldig. Beperk de resultaten zo veel als je kunt. U kunt ook een CROSS JOIN schrijven die functioneel equivalent is aan INNER JOIN.

Dit artikel beëindigt de serie over SQL JOIN's. Voor toekomstige referenties kunt u een bladwijzer maken voor dit artikel. Of voeg het toe aan je verzameling in een browser.

En vergeet niet dit artikel te delen op je favoriete sociale media?


  1. Slaapstand en database met meerdere tenants met behulp van schema's in PostgreSQL

  2. Inleiding tot Multi-Statement Table-Valued Functions (MSTVF) in SQL Server

  3. PostgreSQL-index maken

  4. MySQL relationele databases gebruiken op Fedora 20