Database
 sql >> Baza danych >  >> RDS >> Database

Twój kompletny przewodnik po SQL Join:CROSS JOIN – część 3

CROSS JOIN jest w centrum uwagi. Ten artykuł kończy naszą małą serię publikacji dotyczących SQL JOIN. Jeśli przegapiłeś dwa poprzednie artykuły, zapoznaj się z nimi w następujący sposób:

  • Twój ostateczny przewodnik po SQL Join – część 1:WEWNĘTRZNE DOŁĄCZENIE
  • Twój ostateczny przewodnik po SQL Join – część 2:OUTER JOIN

SQL Server CROSS JOIN jest najprostszym ze wszystkich sprzężeń. Implementuje kombinację 2 tabel bez warunku sprzężenia. Jeśli masz 5 rzędów w jednej tabeli i 3 rzędy w drugiej, otrzymasz 15 kombinacji. Inną definicją jest produkt kartezjański.

Dlaczego miałbyś chcieć łączyć tabele bez warunku łączenia? Poczekaj trochę, bo tam docieramy. Najpierw odnieśmy się do składni.

Składnia SQL CROSS JOIN

Podobnie jak w przypadku INNER JOIN, możesz mieć CROSS JOIN z 2 standardów, SQL-92 i SQL-89. T-SQL obsługuje obie składnie, ale ja wolę SQL-92. Sprawdź część 1 poświęconą INNER JOIN, jeśli chcesz wiedzieć dlaczego.

Składnia 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 

Podobnie jak SQL-89 – INNER JOIN bez warunku złączenia.

5 przykładów użycia SQL Server CROSS JOIN

Możesz się zastanawiać, kiedy możesz użyć SQL CROSS JOIN. Oczywiście przydaje się do kształtowania kombinacji wartości. Co jeszcze?

1. Dane testowe

Jeśli potrzebujesz dużej ilości danych, CROSS JOIN pomoże Ci. Na przykład masz tabelę dostawców i produktów. Kolejna tabela zawiera produkty oferowane przez sprzedawcę. Jeśli jest pusty i potrzebujesz szybko danych, oto, co możesz zrobić:

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

Wygenerował 52 416 rekordów w mojej kopii AdventureWorks . To wystarczy, aby przetestować aplikacje i wydajność. Jeśli jednak prezentujesz swoją aplikację użytkownikom, użyj swojego źródła zamiast danych z naszego przykładu.

2. Uzyskiwanie wyników z brakujących kombinacji

W poprzednim artykule zilustrowaliśmy użycie OUTER JOIN do uzyskania wyników z brakujących wartości. Tym razem użyjemy brakujących kombinacji. Spróbujmy zdobyć produkty, w których Store 294 nie zarabiał pieniędzy.

-- 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 widać, najpierw potrzebujemy wszystkich kombinacji produktów i sklepów – używamy CROSS JOIN. Następnie potrzebujemy listy produktów sprzedanych w okresie styczeń 2014. Na koniec zastosuj LEFT JOIN do tej listy i użyj klauzuli WHERE, aby uzyskać tylko produkty bez sprzedaży. Następnie otrzymujemy informacje o produktach, które nie zostały sprzedane.

3. Tworzenie słów z kombinacji liter

Jeśli lubisz gry słowne z kombinacjami liter, możesz użyć CROSS JOIN z samodołączaniem. Oto próbka składająca się z 3 liter „D”, „O” i „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%'

Podobny kod bez klauzuli WHERE wygeneruje 27 rekordów. Powyższa klauzula WHERE pomogła wyeliminować kombinacje 3 podobnych kombinacji liter, takich jak „DDD” lub „GGG”. Poniżej znajduje się wynik.

Oczywiście, ponieważ nie włożyłem zbyt wiele inteligencji w zapytanie, większość wyników nie zawiera słów. Mimo to pomaga w myślowej części gry.

4. Propozycje posiłków

Wszyscy kochamy jedzenie, ale wybór odpowiedniej kombinacji może być trudny. Podobnie jak w poprzednich przykładowych koncepcjach, oto jak uzyskać możliwe kombinacje posiłków:


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' 

Wynik:

Niektóre z nich są pożądane. Niektórzy mówią „zapomnij o tym!”. To zależy od Twojego gustu.

5. Wybór projektu koszulki

Innym możliwym zastosowaniem CROSS JOIN jest uzyskanie kombinacji wzorów koszul. Oto przykładowy kod:


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 wyniki? Spójrz na jego część na rysunku 3:

Czy możesz podać więcej przykładów?

Wydajność SQL Server CROSS JOIN

Jaki jest haczyk w korzystaniu z CROSS JOIN? Co jest warte, CROSS JOIN może powodować problemy z wydajnością, jeśli nie będziesz ostrożny. Najstraszniejsze jest to, że tworzy produkt z 2 zestawów. Tak więc, bez ograniczania wyników w klauzuli WHERE, Tabela1 z 1000 rekordów CROSS JOIN z Tabelą2 z 1 000 000 rekordów stanie się 1 000 000 000 rekordów. W związku z tym SQL Server ma dużo stron do przeczytania.

Jako przykład rozważ połączenie pracowników płci męskiej i żeńskiej w 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' 

Powyższy kod zawiera wszystkie możliwe pary pracowników płci męskiej i żeńskiej. Mam tylko 17 304 rekordów, ale spójrz na logiczne odczyty na rysunku 4:

Czy widziałeś logiczne odczyty Osoby stół? Czyli 53 268 stron x 8 KB! Nie wspominając o stole roboczym odczyty logiczne są wykonywane w tempdb .

Konkluzja? Sprawdź we/wy STATISTICS i jeśli masz kłopoty z dużymi odczytami logicznymi, wyrażaj zapytanie w inny sposób. Pomocne mogą być dodatkowe warunki w klauzuli WHERE lub podejście „dziel i zwyciężaj”.

Kiedy CROSS JOIN staje się INNER JOIN

Tak to prawda. SQL Server może przetwarzać CROSS JOIN jako INNER JOIN. Wspomnieliśmy wcześniej, że kiedy RIGHT JOIN jest przetwarzane jako LEFT JOIN, może dotyczyć CROSS JOIN. Spójrz na poniższy kod:

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 

Zanim sprawdzimy plan wykonania, przygotujmy odpowiednik 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 

Teraz sprawdź plan wykonania poniżej.

Najwyższym planem jest zapytanie wykorzystujące CROSS JOIN. Dolny plan to zapytanie używające INNER JOIN. Mają ten sam QueryHashPlan .

Czy zauważyłeś Hash Match operator najwyższego planu? To WEWNĘTRZNE DOŁĄCZENIE. Ale użyliśmy CROSS JOIN w kodzie. Klauzula WHERE w pierwszym zapytaniu (WHERE c.PersonID =P.BusinessEntityID ) wymusiło w wynikach kombinacje tylko z równymi kluczami. Logicznie więc jest to WEWNĘTRZNE POŁĄCZENIE.

Który jest lepszy? To twój osobisty wybór. Preferuję INNER JOIN, ponieważ intencją jest łączenie 2 tabel za pomocą równych kluczy. Użycie INNER JOIN sprawia, że ​​jest to bardzo jasne. Ale to tylko ja.

Wniosek

CROSS JOIN jest dobry, aby dać ci wszystkie możliwe kombinacje wartości. Zostałeś jednak ostrzeżony, że może to spowodować pewnego rodzaju „eksplozję” danych. Używaj tego DOŁĄCZ ostrożnie. Ogranicz wyniki tak bardzo, jak możesz. Możesz także napisać CROSS JOIN, który jest funkcjonalnie równoważny INNER JOIN.

Ten artykuł kończy serię dotyczącą SQL JOIN. Aby uzyskać przyszłe odniesienia, możesz dodać ten artykuł do zakładek. Lub dodaj go do swojej kolekcji w przeglądarce.

I nie zapomnij udostępnić tego artykułu w swoich ulubionych mediach społecznościowych?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL INSERT dla początkujących

  2. Zagnieżdżone funkcje okien w SQL

  3. Używanie AT TIME ZONE do naprawy starego raportu

  4. Przykład poprawy wydajności zapytań za pomocą indeksów

  5. Dwie osobliwości podziału