Database
 sql >> база данни >  >> RDS >> Database

Вашето окончателно ръководство за SQL присъединяване:КРЪСТО ПРИСЪЕДИНЯВАНЕ – част 3

CROSS JOIN е в светлината на прожекторите. Тази статия завършва нашата малка серия от публикации, свързани с SQL JOIN. Ако сте пропуснали предишните две статии, обърнете се към тях по следния начин:

  • Вашето окончателно ръководство за SQL присъединяване – част 1:ВЪТРЕШНО ПРИСЪЕДИНЕНИЕ
  • Вашето окончателно ръководство за SQL присъединяване – част 2:OUTER JOIN

SQL Server CROSS JOIN е най-простото от всички присъединявания. Той реализира комбинация от 2 таблици без условие за присъединяване. Ако имате 5 реда в една таблица и 3 реда в друга, получавате 15 комбинации. Друго определение е декартов продукт.

Сега, защо бихте искали да комбинирате таблици без условие за присъединяване? Изчакай малко, защото стигаме до там. Първо, нека се обърнем към синтаксиса.

SQL CROSS JOIN Синтаксис

Подобно на INNER JOIN, можете да имате CROSS JOIN от 2 стандарта, SQL-92 и SQL-89. T-SQL поддържа и двата синтаксиса, но аз предпочитам SQL-92. Проверете част 1, посветена на INNER JOIN, ако искате да знаете защо.

Синтаксис на 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 

Подобно на SQL-89 – INNER JOIN без условието за присъединяване.

5 примера за използване на SQL Server CROSS JOIN

Може да се чудите кога можете да използвате SQL CROSS JOIN. Разбира се, това е полезно за оформяне на комбинации от стойности. Какво друго?

1. Тестови данни

Ако имате нужда от голямо количество данни, CROSS JOIN ще ви помогне. Например, имате таблица с доставчици и продукти. Друга таблица съдържа продукти, които продавачът предлага. Ако е празен и имате нужда от данни бързо, ето какво можете да направите:

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

Той генерира 52 416 записа в моето копие на AdventureWorks . Това е достатъчно за тестване на приложения и производителност. Ако обаче представяте приложението си на потребителите, използвайте своя източник вместо тези данни от нашия пример.

2. Получаване на резултати от липсващи комбинации

В предишната статия илюстрирахме използването на OUTER JOIN за получаване на резултати от липсващи стойности. Този път ще използваме липсващи комбинации. Нека опитаме да вземем продуктите, където Store 294 не е спечелил пари.

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

Както можете да видите, първо се нуждаем от всички комбинации от продукти и магазини – ние използваме КРЪСТНО ПРИСЪЕДИНЕНИЕ. След това се нуждаем от списък на продадените продукти за периода януари 2014 г. Накрая приложете LEFT JOIN към този списък и използвайте клаузата WHERE, за да получите само продуктите без продажби. След това получаваме информация за продукти, които не са били продадени.

3. Образуване на думи от съчетания на букви

Ако харесвате игри с думи с комбинации от букви, можете да използвате CROSS JOIN със самостоятелно присъединяване. Ето пример, използващ 3 букви „D“, „O“ и „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%'

Подобен код без клаузата WHERE ще генерира 27 записа. Клаузата WHERE по-горе помогна за премахването на комбинации от 3 подобни комбинации от букви като „DDD“ или „GGG“. По-долу е резултатът.

Разбира се, тъй като не вложих много интелигентност в заявката, повечето от резултатите не са думи. Все пак помага в мисловната част на играта.

4. Предложения за хранене

Всички обичаме храната, но може да е трудно да изберем правилните комбинации. Както в предишните примерни концепции, ето как да получите възможни комбинации от храна:


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' 

Резултатът:

Някои от тях са желани. Някои казват „забрави!“ Зависи от вашия вкус.

5. Избор на дизайн на тениска

Друга възможна употреба на CROSS JOIN е получаването на дизайнерски комбинации за ризи. Ето примерен код:


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'

А резултатите? Разгледайте частта му на фигура 3:

Можете ли да се сетите за още примери?

Ефективност на КРЪСТО ПРИСЪЕДИНЯВАНЕ на SQL сървър

Каква е уловката в използването на CROSS JOIN? За какво си струва, CROSS JOIN може да причини проблеми с производителността, ако не сте внимателни. Най-страшното е, че образува продукт от 2 комплекта. По този начин, без ограничаване на резултатите в клауза WHERE, Таблица1 с 1000 записа CROSS JOIN с Таблица2 с 1 000 000 записа ще стане 1 000 000 000 записа. Следователно това са много страници за четене от SQL Server.

Като пример помислете за сдвояване на служители мъже и жени в 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' 

Горният код ви дава всички възможни двойки служители мъже и жени. Получих само 17 304 записа, но вижте логическите показания на фигура 4:

Видяхте ли логичните показания на Лицето маса? Това е четене на 53,268 x 8KB страници! Да не говорим за Работната маса логическите четения се извършват в tempdb .

Заключението? Проверете IO STATISTICS и ако ви притеснява да видите големи логически показания, изразете заявка по различен начин. Допълнителни условия в клаузата WHERE или подходът разделяй и владей могат да помогнат.

Когато КРЪСТОТО СЪЕДИНЕНИЕ се превърне във ВЪТРЕШНО СЪЕДИНЕНИЕ

Да, така е. SQL Server може да обработва CROSS JOIN като INNER JOIN. По-рано споменахме, че когато ДЯСНО ПРИСЪЕДИНЕНИЕ се обработва като ЛЯВО ПРИСЪЕДИНЯВАНЕ, то може да се приложи и за КРЪСТО ПРИСЪЕДИНЕНИЕ. Разгледайте кода по-долу:

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 

Преди да проверим плана за изпълнение, нека имаме еквивалента на 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 

Сега проверете плана за изпълнение по-долу.

Най-горният план е заявката, използваща CROSS JOIN. Долният план е заявката, използваща INNER JOIN. Те имат същия QueryHashPlan .

Забелязахте ли Hash Match оператор на топ план? Това е ВЪТРЕШНО ПРИСЪЕДИНЕНИЕ. Но ние използвахме CROSS JOIN в кода. Клаузата WHERE в първата заявка (WHERE c.PersonID =P.BusinessEntityID ) принуди резултатите да имат комбинации само с еднакви ключове. Така че, логично това е ВЪТРЕШНО ПРИСЪЕДИНЕНИЕ.

Кой е по-добър? Това е ваш личен избор. Предпочитам INNER JOIN, защото намерението е да се обединят 2 таблици с еднакви ключове. Използването на INNER JOIN го прави много ясно. Но това съм само аз.

Заключение

CROSS JOIN е добър за предоставяне на всички възможни комбинации от стойности. Бяхте предупредени обаче, че това може да причини някакъв вид „експлозия“ на данни. Използвайте внимателно това JOIN. Ограничете резултатите, доколкото можете. Освен това можете да напишете КРЪСТНО ПРИСЪЕДИНЕНИЕ, което е функционално еквивалентно на INNER JOIN.

Тази статия завършва поредицата за SQL JOIN. За бъдещи справки можете да маркирате тази статия. Или го добавете към колекцията си в браузър.

И не забравяйте да споделите тази статия в любимите си социални медии?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Оператори на T-SQL SET Част 2:INTERSECT и EXCEPT

  2. Блокчейн:какво е това, как работи и какво означава за големи данни

  3. Обосноваване на новия Mac Pro

  4. Разделяне на бюджет

  5. Свързване на IBM DB2 с IRI софтуер