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

列と複数の行で1つの行の複数の列にグループ化する

    コメントで述べたように、ここで必要なのはPIVOTです。 またはクロスタブ;私は後者の方が好きなので、これから使用します。

    これに対する非動的な解決策は次のようになります。

    WITH RNs AS(
        SELECT WorkOrder,
               TestType,
               Result,
               ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column
        FROM dbo.Result)
    SELECT WorkOrder,
           TestType,
           MAX(CASE RN WHEN 1 THEN Result END) AS Result1,
           MAX(CASE RN WHEN 2 THEN Result END) AS Result2,
           MAX(CASE RN WHEN 3 THEN Result END) AS Result3
    FROM RNs R
    GROUP BY WorkOrder,
             TestType;
    

    ただし、問題は、これにより3つの結果に「ロック」されることですが、結果の数が不確定であることを示唆しています。したがって、動的なソリューションが必要です。

    以下は100件までの結果になります。 必要を行う場合 より多くの列を追加してから、CROSS JOINを追加します sからN CTEのTally 。この結果は次のようなものです(これはかなり厄介です)。

    DECLARE @SQL nvarchar(MAX),
            @CRLF nchar(2) = NCHAR(13) + NCHAR(10),
            @MaxTally int;
    
    SELECT @MaxTally = MAX(C)
    FROM (SELECT COUNT(*) AS C
          FROM dbo.Result
          GROUP BY WorkOrder,
                   TestType) R;
    
    WITH N AS(
        SELECT N
        FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
    Tally AS(
        SELECT TOP (@MaxTally) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
        FROM N N1, N N2) --100 rows, add more Ns for more rows
    SELECT @SQL = N'WITH RNs AS(' + @CRLF +
                  N'    SELECT WorkOrder,' + @CRLF +
                  N'           TestType,' + @CRLF +
                  N'           Result,' + @CRLF +
                  N'           ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column' + @CRLF +
                  N'    FROM dbo.Result)' + @CRLF +
                  N'SELECT WorkOrder,' + @CRLF +
                  N'       TestType,' + @CRLF +
                  --Using FOR XML PATH due to not knowing SQL Server version
                  STUFF((SELECT N',' + @CRLF +
                                CONCAT(N'       MAX(CASE RN WHEN ',T.I,N' THEN Result END) AS Result',T.I)
                         FROM Tally T
                         ORDER BY T.I ASC
                         FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,3,N'') + @CRLF +
                  N'FROM RNs R' + @CRLF +
                  N'GROUP BY WorkOrder,' + @CRLF +
                  N'         TestType;';
    
    PRINT @SQL; --Your best friend.
    
    EXEC sys.sp_executesql @SQL;
    


    1. SSISの増分負荷

    2. mysql_num_rows()は、パラメーター1がリソースであると想定しています。ブール値は次のように指定されます。

    3. SQL Serverに監査証跡を実装する最良の方法は?

    4. SQL Serverで複合主キーを作成する方法(T-SQLの例)