Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Grupuj według kolumny i wielu wierszy w jeden wiersz wiele kolumn

Jak wspomniałem w komentarzach, potrzebujesz tutaj PIVOT lub Zakładka krzyżowa; Wolę to drugie, więc z czego będę korzystać.

Niedynamiczne rozwiązanie tego byłoby następujące:

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;

Problem polega jednak na tym, że to „blokuje” Cię w 3 wynikach, ale sugerujesz, że liczba wyników jest nieokreślona. Dlatego potrzebujesz dynamicznego rozwiązania.

Poniższe będzie działać do 100 wyników. jeśli potrzebujesz więcej kolumn niż, a następnie dodaj więcej CROSS JOIN s do N w CTE Tally . Ten wynik jest podobny do tego (co jest dość niechlujne).

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego podczas nawiązywania połączenia z programem SQL Server wystąpił błąd związany z siecią lub specyficzny dla wystąpienia?

  2. Niestandardowe formatowanie daty/godziny w SQL Server

  3. Czy można uzyskać dostęp do bazy danych .mdf bez SQL Server?

  4. Czy mogę ustawić domyślny schemat dla procedury składowanej?

  5. JDBC SQLServerException:Ten sterownik nie jest skonfigurowany do zintegrowanego uwierzytelniania.