1

次の 3 つのテーブルがあるとします。

  • Cars (CarID) には、10 個の異なる車の行が含まれています。
  • SafetyTests (TestID, TestName) には、20 の個別の安全性テスト行が含まれています。
  • TestResults (ID、TestID、CarID、TestValue) には、0 ~ 200 の安全テスト行の数値が含まれます。

安全性テスト テーブルには、Cars テーブルの 10 台の車に対して実行された各安全性テストの結果が含まれています。最大 20 の安全性テストがあります。これは明らかに、SafetyTests テーブルの選択ステートメントから取得されます。ただし、10台の車の中には20回のテストすべてを実行したものもあれば、5回しか実行していないものもあります.

車ごとに 20 の結果を表示する 10 x 20 のマトリックスを作成したいと考えています (20 の安全性テスト結果がない場合でも)。車でテストがまだ実行されていない場合は、テスト名だけが表示されますが、値はゼロ (または null) です。

これは、SafetyTests テーブルに対する SELECT (テスト ID の個別のリストを取得するため) と、Cars と TestResults の間の JOIN の組み合わせに対する LEFT JOIN であると考えましたが、問題は、欠落しているテストに対して NULL の CAR ID を返すことです。 Car テーブルに一致するものはありませんでした。

4

2 に答える 2

4

車から安全性テストにクロス ジョインできます。次に、TestResults に左ジョインします。クロス ジョインにより 10 x 20 行列が得られ、左ジョインにより結果が得られます。

ISNULL または COALESCE を使用して、結果セットの null をゼロに置き換えます

例えば

SELECT car.name, testresults.testname, isnull(testresults.result, 0) FROM 
cars CROSS JOIN
safetytests
LEFT JOIN testresults on safetytests.testid = testresults.testid AND car.id = testresults.carid

これがクロス結合の機能です

誰かが提案したようにsqlfiddleをしました:)そのサイトは本当に良いです

http://sqlfiddle.com/#!3/2bc73/2

于 2012-05-18T09:00:00.977 に答える
3

私が質問を正しく理解していれば、次のような 10x20 の結果セットが必要です。

CarID   |   Test1   |   Test2   |   ....    |   Test20
-------------------------------------------------------
1       |   NULL    |   Fail    |   ....    |   true
2       |   2       |   Pass    |   ....    |   false

これを行うには、SQL-Server 2008 のPIVOT機能を利用します。

WITH Results AS
(   SELECT  cars.CarID,
            TestName,
            TestValue
    FROM    Cars
            CROSS JOIN SafetyTests s
            LEFT JOIN TestResults res
                ON res.CarID = Cars.CarID
                AND res.TestID = s.TestID
) 
SELECT  *
FROM    Results
        PIVOT
        (   MAX(TestValue)
            FOR TestName IN ([TesT1], [Test2], [Test3], [Test4]) 
            -- LIST ALL 20 TEST NAMES HERE
        ) pvt

これの欠点は、ピボットするすべてのテスト名を明示的にリストする必要があることです。そうしないと、列として表示されませんが、これを動的に行うことは可能です。以下は基本的に上記とまったく同じクエリですが、すべての列名のリストを動的に生成し、それらをクエリに挿入しました。

DECLARE @SQL NVARCHAR(MAX) = ''

SELECT  @SQL = @SQL + ',' + QUOTENAME(TestName)
FROM    SafetyTests

SET @SQL = 'WITH Results AS
            (   SELECT  Cars.CarID,
                        TestName,
                        TestValue
                FROM    Cars
                        CROSS JOIN SafetyTests s
                        LEFT JOIN TestResults res
                            ON res.CarID = Cars.CarID
                            AND res.TestID = s.TestID
            ) 
            SELECT  *
            FROM    Results
                    PIVOT
                    (   MAX(TestValue)
                        FOR TestName IN (' + STUFF(@SQL, 1, 1, '') + ')
                    ) pvt'

EXECUTE SP_EXECUTESQL @SQL

SQL フィドル

于 2012-05-18T09:12:06.517 に答える