CROSS JOIN je v centru pozornosti. Tento článek dokončuje naši malou sérii publikací souvisejících s SQL JOIN. Pokud jste přehlédli předchozí dva články, podívejte se na ně následovně:
- Váš dokonalý průvodce SQL Join – Část 1:INNER JOIN
- Váš dokonalý průvodce SQL Join – Část 2:OUTER JOIN
SQL Server CROSS JOIN je nejjednodušší ze všech spojení. Implementuje kombinaci 2 tabulek bez podmínky spojení. Pokud máte 5 řádků v jedné tabulce a 3 řádky v jiné, dostanete 15 kombinací. Další definicí je kartézský součin.
Proč byste chtěli kombinovat tabulky bez podmínky spojení? Chvíli vydržte, protože se tam dostáváme. Nejprve se podívejme na syntaxi.
Syntaxe SQL CROSS JOIN
Stejně jako u INNER JOIN můžete mít CROSS JOIN ze 2 standardů, SQL-92 a SQL-89. T-SQL podporuje obě syntaxe, ale já preferuji SQL-92. Pokud chcete vědět proč, podívejte se na část 1 věnovanou INNER JOIN.
Syntaxe 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
Podobně jako SQL-89 – INNER JOIN bez podmínky spojení.
5 příkladů použití SQL Server CROSS JOIN
Možná se divíte, kdy můžete použít SQL CROSS JOIN. Samozřejmě je to užitečné pro vytváření kombinací hodnot. Co jiného?
1. Testovací data
Pokud potřebujete velké množství dat, pomůže vám CROSS JOIN. Máte například tabulku prodejců a produktů. Další tabulka obsahuje produkty, které prodejce nabízí. Pokud je prázdný a potřebujete rychle data, můžete udělat toto:
SELECT
P.ProductID
,v.BusinessEntityID AS VendorID
FROM
Production.Product p
CROSS JOIN Purchasing.Vendor v
Vygenerovalo to 52 416 záznamů v mé kopii AdventureWorks . To stačí k testování aplikací a výkonu. Pokud však svou aplikaci prezentujete uživatelům, použijte místo těchto dat z našeho příkladu svůj zdroj.
2. Získávání výsledků z chybějících kombinací
V předchozím článku jsme ilustrovali použití OUTER JOIN pro získání výsledků z chybějících hodnot. Tentokrát použijeme chybějící kombinace. Zkusme získat produkty tam, kde Store 294 nevydělával peníze.
-- 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
Jak vidíte, nejprve potřebujeme všechny kombinace produktů a prodejen – používáme CROSS JOIN. Poté potřebujeme seznam produktů prodaných za období ledna 2014. Nakonec na tento seznam použijte LEFT JOIN a použijte klauzuli WHERE, abyste získali pouze produkty bez prodeje. Poté získáme informace o produktech, které nebyly prodány.
3. Tvoření slov z kombinací písmen
Pokud máte rádi slovní hry s kombinacemi písmen, můžete použít CROSS JOIN s vlastním spojením. Zde je ukázka používající 3 písmena „D“, „O“ a „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%'
Podobný kód bez klauzule WHERE vygeneruje 27 záznamů. Výše uvedená klauzule WHERE pomohla odstranit kombinace 3 podobných kombinací písmen, jako je „DDD“ nebo „GGG“. Níže je výsledek.
Samozřejmě, protože jsem do dotazu nevložil mnoho inteligence, většina výsledků nejsou slova. Přesto to pomáhá v myšlenkové části hry.
4. Doporučení k jídlu
Všichni milujeme jídlo, ale může být těžké vybrat ty správné kombinace. Stejně jako v předchozích příkladech konceptů, zde je návod, jak získat možné kombinace jídel:
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'
Výsledek:
Některé z nich jsou žádoucí. Někteří říkají:‚zapomeňte!‘ Záleží na vašem vkusu.
5. Výběr designu trička
Dalším možným využitím CROSS JOIN je získání designových kombinací pro košile. Zde je ukázkový kód:
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'
A výsledky? Podívejte se na jeho část na obrázku 3:
Napadají vás nějaké další příklady?
Výkon SQL Server CROSS JOIN
Jaký je háček v používání CROSS JOIN? Pokud si nedáte pozor, CROSS JOIN může způsobit problémy s výkonem. Nejděsivější na tom je, že tvoří produkt 2 sad. Bez omezení tedy vznikne klauzule WHERE, Tabulka1 s 1000 záznamy CROSS JOIN s Tabulkou2 s 1 000 000 záznamy se stane 1 000 000 000 záznamů. V důsledku toho je to mnoho stránek ke čtení SQL Serverem.
Jako příklad zvažte spárování zaměstnanců a zaměstnanců v 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'
Výše uvedený kód vám poskytuje všechny možné páry mužů a žen. Mám pouze 17 304 záznamů, ale podívejte se na logická čtení na obrázku 4:
Viděli jste logické čtení Osoby stůl? To je 53 268 x 8 kB stránek! Nemluvě o WorkTable logická čtení se provádějí v tempdb .
Závěr? Zkontrolujte vstup STATISTICS IO a pokud vám dělá potíže vidět velká logická čtení, vyjádřete dotaz jinak. Pomoci mohou další podmínky v klauzuli WHERE nebo přístup rozděl a panuj.
Když se CROSS JOIN stane INNER JOIN
Ano to je správně. SQL Server může zpracovat CROSS JOIN jako INNER JOIN. Již jsme zmínili, že když je RIGHT JOIN zpracován jako LEFT JOIN, může se vztahovat na CROSS JOIN. Podívejte se na kód níže:
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
Než se podíváme na Prováděcí plán, pojďme mít ekvivalent 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
Nyní zkontrolujte prováděcí plán níže.
Horní plán je dotaz pomocí CROSS JOIN. Spodní plán je dotaz pomocí INNER JOIN. Mají stejný QueryHashPlan .
Všimli jste si Hash Match? provozovatel top plánu? Je to VNITŘNÍ SPOJENÍ. Ale v kódu jsme použili CROSS JOIN. Klauzule WHERE v prvním dotazu (WHERE c.PersonID =P.BusinessEntityID ) vynutil, aby výsledky měly kombinace pouze se stejnými klíči. Logicky je to tedy INNER JOIN.
Který je lepší? Je to vaše osobní volba. Dávám přednost INNER JOIN, protože záměrem je spojit 2 stoly stejnými klíči. Pomocí INNER JOIN je to velmi jasné. Ale to jsem jen já.
Závěr
CROSS JOIN je dobré pro poskytování všech možných kombinací hodnot. Byli jste však varováni, že to může způsobit určitý druh „výbuchu“ dat. Tento JOIN používejte opatrně. Omezte výsledky, jak jen můžete. Také můžete napsat CROSS JOIN, který je funkčně ekvivalentní INNER JOIN.
Tento článek končí sérii o SQL JOINs. Pro budoucí reference si můžete tento článek uložit do záložek. Nebo ji přidejte do své sbírky v prohlížeči.
A nezapomeňte tento článek sdílet na svých oblíbených sociálních sítích?