sql >> データベース >  >> RDS >> Database

SQL結合の究極のガイド:CROSS JOIN –パート3

    CROSSJOINが脚光を浴びています。この記事は、SQLJOIN関連の小さなシリーズの出版物を締めくくるものです。前の2つの記事を見逃した場合は、次のように参照してください。

    • SQL結合の究極のガイド–パート1:内部結合
    • SQL結合の究極のガイド–パート2:外部結合

    SQL Server CROSS JOINは、すべての結合の中で最も単純です。結合条件なしで2つのテーブルの組み合わせを実装します。 1つのテーブルに5つの行があり、別のテーブルに3つの行がある場合、15の組み合わせが得られます。別の定義はデカルト積です。

    では、なぜ結合条件なしでテーブルを結合したいのでしょうか。そこに着いているので少し待ってください。まず、構文を参照してみましょう。

    SQLCROSSJOIN構文

    INNER JOINと同様に、SQL-92とSQL-89の2つの標準からのCROSSJOINを使用できます。 T-SQLは両方の構文をサポートしていますが、私はSQL-92を好みます。理由を知りたい場合は、INNERJOIN専用のパート1を確認してください。

    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によく似ています–結合条件のないINNERJOIN。

    5 SQL ServerCROSSJOINの使用例

    SQLCROSSJOINをいつ使用できるのか疑問に思われるかもしれません。もちろん、値の組み合わせを形成するのに役立ちます。他に何がありますか?

    1。テストデータ

    大量のデータが必要な場合は、CROSSJOINが役立ちます。たとえば、ベンダーと製品のテーブルがあります。別の表には、ベンダーが提供する製品が含まれています。空でデータがすぐに必要な場合は、次のことができます。

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

    AdventureWorksのコピーで52,416レコードが生成されました 。アプリとパフォーマンスをテストするにはこれで十分です。ただし、アプリをユーザーに提示する場合は、この例のデータの代わりにソースを使用してください。

    2。欠落している組み合わせから結果を得る

    前回の記事では、欠落している値から結果を取得するためのOUTERJOINの使用法を説明しました。今回は不足している組み合わせを使用します。 Store294が収益を上げなかった製品を入手してみましょう。

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

    ご覧のとおり、最初にすべての商品と店舗の組み合わせが必要です。CROSSJOINを使用しています。次に、2014年1月の期間に販売された製品のリストが必要です。最後に、そのリストにLEFT JOINを適用し、WHERE句を使用して、売上のない製品のみを取得します。次に、販売されなかった製品に関する情報を取得します。

    3。文字の組み合わせから単語を形成する

    文字の組み合わせを使用したワードゲームに興味がある場合は、CROSSJOINを自己結合で使用できます。これは、「D」、「O」、「G」の3文字を使用したサンプルです。

    
    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句は、「DDD」や「GGG」などの3つの類似した文字の組み合わせの組み合わせを排除するのに役立ちました。結果は以下のとおりです。

    もちろん、私はクエリにあまりインテリジェンスを入れていなかったので、結果のほとんどは単語ではありません。それでも、それはゲームの思考部分に役立ちます。

    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。 Tシャツのデザインセレクション

    CROSS JOINのもう1つの可能な用途は、シャツのデザインの組み合わせを取得することです。サンプルコードは次のとおりです:

    
    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 ServerCROSSJOINパフォーマンス

    CROSS JOINを使用する際の落とし穴は何ですか?注意しないと、CROSSJOINによってパフォーマンスの問題が発生する可能性があります。一番怖いのは2セットの商品です。したがって、結果を制限せずにWHERE句を使用すると、 Table1 1000レコードでCROSSJOINwith Table2 1,000,000レコードの場合、1,000,000,000レコードになります。したがって、SQLServerで読み取るページはたくさんあります。

    例として、 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の論理読み取りを見てください。

    Personの論理的な読み取りを見ましたか テーブル?これは53,268x8KBのページを読んでいます。 WorkTableは言うまでもありません 論理読み取りはtempdbで行われます 。

    結論? STATISTICS IOを確認し、大きな論理読み取りが表示されない場合は、クエリを別の方法で表現します。 WHERE句の追加条件または分割統治法が役立つ場合があります。

    クロスジョインがインナージョインになったとき

    はい、そうです。 SQL Serverは、CROSSJOINをINNERJOINとして処理できます。 RIGHTJOINがLEFTJOINとして処理される場合、CROSSJOINに適用できることは前述しました。以下のコードをご覧ください:

    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 
    

    実行プランを確認する前に、INNERJOINに相当するものを用意しましょう。

    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 
    

    次に、以下の実行計画を確認してください。

    一番上の計画は、CROSSJOINを使用したクエリです。一番下の計画は、INNERJOINを使用したクエリです。それらは同じQueryHashPlanを持っています 。

    ハッシュマッチに気づきましたか トッププランのオペレーター?それは内部の結合です。ただし、コードではCROSSJOINを使用しました。最初のクエリのWHERE句( WHERE c.PersonID =P.BusinessEntityID )結果に等しいキーのみの組み合わせを強制しました。つまり、論理的には内部結合です。

    どちらがいいですか?それはあなたの個人的な選択です。等しいキーで2つのテーブルを結合することが目的であるため、私はINNERJOINを好みます。 INNER JOINを使用すると、非常に明確になります。しかし、それは私だけです。

    結論

    CROSS JOINは、考えられるすべての値の組み合わせを提供するのに適しています。ただし、ある種のデータの「爆発」を引き起こす可能性があると警告されています。このJOINは慎重に使用してください。結果をできるだけ制限します。また、INNERJOINと機能的に同等のCROSSJOINを作成することもできます。

    この記事は、SQLJOINに関するシリーズを終了します。今後の参考のために、この記事をブックマークすることができます。または、ブラウザでコレクションに追加します。

    そして、この記事をお気に入りのソーシャルメディアで共有することを忘れないでください?


    1. ExecuteBatchメソッドは、Javaで値-2の配列を返します

    2. Postgresql9.4のスペースを含む誤った並べ替え/照合/順序

    3. PostgreSQLのすべての関数を一覧表示する3つの方法

    4. SQLまたはMySQLでJOINキーワードを使用しない結合に何か問題がありますか?