Database
 sql >> Base de données >  >> RDS >> Database

Votre guide ultime de la jointure SQL :CROSS JOIN – Partie 3

CROSS JOIN est à l'honneur. Cet article termine notre petite série de publications liées à SQL JOIN. Si vous avez manqué les deux articles précédents, consultez-les comme suit :

  • Votre guide ultime de la jointure SQL – Partie 1 :INNER JOIN
  • Votre guide ultime de la jointure SQL – Partie 2 :OUTER JOIN

SQL Server CROSS JOIN est la plus simple de toutes les jointures. Il implémente une combinaison de 2 tables sans condition de jointure. Si vous avez 5 lignes dans un tableau et 3 lignes dans un autre, vous obtenez 15 combinaisons. Une autre définition est un produit cartésien.

Maintenant, pourquoi voudriez-vous combiner des tables sans condition de jointure ? Attendez un peu car nous y arrivons. Tout d'abord, référons-nous à la syntaxe.

Syntaxe SQL CROSS JOIN

Comme avec INNER JOIN, vous pouvez avoir un CROSS JOIN à partir de 2 standards, SQL-92 et SQL-89. T-SQL prend en charge les deux syntaxes, mais je préfère SQL-92. Consultez la partie 1 dédiée à INNER JOIN si vous voulez savoir pourquoi.

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 

Tout comme SQL-89 - INNER JOIN sans la condition de jointure.

5 exemples d'utilisation de SQL Server CROSS JOIN

Vous vous demandez peut-être quand vous pouvez utiliser SQL CROSS JOIN. Bien sûr, c'est utile pour façonner des combinaisons de valeurs. Quoi d'autre ?

1. Données de test

Si vous avez besoin d'une grande quantité de données, un CROSS JOIN vous aidera. Par exemple, vous avez une table de fournisseurs et de produits. Une autre table contient les produits proposés par le fournisseur. S'il est vide et que vous avez besoin de données rapidement, voici ce que vous pouvez faire :

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

Il a généré 52 416 enregistrements dans ma copie de AdventureWorks . C'est suffisant pour tester les applications et les performances. Cependant, si vous présentez votre application aux utilisateurs, utilisez votre source au lieu de ces données de notre exemple.

2. Obtenir des résultats à partir des combinaisons manquantes

Dans l'article précédent, nous avons illustré l'utilisation de OUTER JOIN pour obtenir des résultats à partir de valeurs manquantes. Cette fois, nous utiliserons les combinaisons manquantes. Essayons d'obtenir les produits là où Store 294 n'a pas fait d'argent.

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

Comme vous pouvez le voir, nous avons d'abord besoin de toutes les combinaisons de produits et de magasins - nous utilisons un CROSS JOIN. Ensuite, nous avons besoin d'une liste de produits vendus pour la période de janvier 2014. Enfin, appliquez LEFT JOIN à cette liste et utilisez la clause WHERE pour obtenir uniquement les produits sans ventes. Ensuite, nous obtenons des informations sur les produits qui n'ont pas été vendus.

3. Former des mots à partir de combinaisons de lettres

Si vous aimez les jeux de mots avec des combinaisons de lettres, vous pouvez utiliser CROSS JOIN avec une auto-jointure. Voici un exemple utilisant 3 lettres "D", "O" et "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%'

Un code similaire sans la clause WHERE générera 27 enregistrements. La clause WHERE ci-dessus a aidé à éliminer les combinaisons de 3 combinaisons de lettres similaires comme « DDD » ou « GGG ». Ci-dessous le résultat.

Bien sûr, comme je n'ai pas mis beaucoup d'intelligence dans la requête, la plupart des résultats sont des non-mots. Pourtant, cela aide dans la partie de réflexion du jeu.

4. Suggestions de repas

Nous aimons tous la nourriture, mais il peut être difficile de choisir les bonnes combinaisons. Comme dans les exemples de concepts précédents, voici comment obtenir des combinaisons de repas possibles :


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' 

Le résultat :

Certains d'entre eux sont souhaitables. Certains disent "oublie ça !" Cela dépend de vos goûts.

5. Sélection de motifs de t-shirts

Une autre utilisation possible de CROSS JOIN consiste à obtenir des combinaisons de motifs pour les chemises. Voici un exemple de code :


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'

Et les résultats ? Jetez un œil à sa partie dans la figure 3 :

Pouvez-vous penser à d'autres exemples ?

Performances CROSS JOIN SQL Server

Quel est l'intérêt d'utiliser CROSS JOIN ? Pour ce que ça vaut, CROSS JOIN peut causer des problèmes de performances si vous ne faites pas attention. La partie la plus effrayante est qu'elle forme un produit de 2 ensembles. Ainsi, sans limiter les résultats dans une clause WHERE, Table1 avec 1000 enregistrements CROSS JOIN avec Table2 avec 1 000 000 enregistrements deviendra 1 000 000 000 enregistrements. Par conséquent, cela fait beaucoup de pages à lire par SQL Server.

Par exemple, envisagez de jumeler des employés masculins et féminins dans 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' 

Le code ci-dessus vous donne toutes les paires possibles d'employés masculins et féminins. Je n'ai obtenu que 17 304 enregistrements, mais regardez les lectures logiques de la figure 4 :

Avez-vous vu les lectures logiques de la Personne table? C'est lire 53 268 pages de 8 Ko ! Sans oublier la WorkTable les lectures logiques sont effectuées dans tempdb .

La conclusion? Vérifiez les STATISTICS IO, et si cela vous dérange de voir de grandes lectures logiques, exprimez une requête différemment. Des conditions supplémentaires dans la clause WHERE ou une approche diviser pour mieux régner peuvent aider.

Quand un CROSS JOIN devient un INNER JOIN

Oui c'est vrai. SQL Server peut traiter une CROSS JOIN comme une INNER JOIN. Nous avons mentionné précédemment que lorsqu'un RIGHT JOIN est traité comme un LEFT JOIN, il peut s'appliquer à CROSS JOIN. Jetez un œil au code ci-dessous :

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 

Avant de vérifier le plan d'exécution, prenons l'équivalent 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 

Maintenant, vérifiez le plan d'exécution ci-dessous.

Le plan supérieur est la requête utilisant un CROSS JOIN. Le plan inférieur est la requête utilisant un INNER JOIN. Ils ont le même QueryHashPlan .

Avez-vous remarqué la Hash Match opérateur du top plan ? C'est une INNER JOIN. Mais nous avons utilisé un CROSS JOIN dans le code. La clause WHERE dans la première requête (WHERE c.PersonID =P.BusinessEntityID ) a forcé les résultats à n'avoir que des combinaisons avec des clés égales. Donc, logiquement, c'est un INNER JOIN.

Quel est le meilleur? C'est votre choix personnel. Je préfère INNER JOIN car l'intention est de joindre 2 tables avec des clés égales. L'utilisation de INNER JOIN le rend très clair. Mais ce n'est que moi.

Conclusion

CROSS JOIN est bon pour vous donner toutes les combinaisons de valeurs possibles. Vous avez été averti, cependant, que cela peut provoquer une sorte d'"explosion" des données. Utilisez ce JOIN avec précaution. Limitez les résultats autant que vous le pouvez. En outre, vous pouvez écrire un CROSS JOIN qui est fonctionnellement équivalent à INNER JOIN.

Cet article met fin à la série sur les SQL JOIN. Pour de futures références, vous pouvez ajouter cet article à vos favoris. Ou ajoutez-le à votre collection dans un navigateur.

Et n'oubliez pas de partager cet article sur vos réseaux sociaux préférés ?