Как перенести строки данных в одну строку с разными столбцами в SQL Server - PullRequest
0 голосов
/ 04 апреля 2019

В настоящее время у меня есть данные из #temp, где я извлекаю их из других таблиц. Формат таблицы #temp следующий

WorkerID MainDoc    SubDoc    Value   TimeStamp
-------- --------  ---------  -----   ---------
1224       Doc1       A1       abc     11:40
1234       Doc1       A2       def     11:40
1224       Doc1       B1       30      11.40
1234       Doc1       B2       40      11:40
1224       Doc1       C1       50      11:40
1234       Doc1       C1       51      11:50
1224       Doc1       C2       60      11:40
1234       Doc1       C2       61      11:50
1235       Doc1       A1       fgf     11:55
1235       Doc1       A2       vbv     11:55

Мне нужно переместить эти строки в одну строку с последним значением метки времени, когда WorkerID совпадает и формат выглядит следующим образом

WorkerID  MainDoc   Value(1)   Value(2)  Value(3)   Value(4)   Value(5) Value(6)
--------  -------   --------   --------  --------   --------   -------- --------
  1234    Doc1      abc        def        30          40         51      61
  1235    Doc1      fgf        vbv       NULL        NULL       NULL    NULL

Как так, как я могу сделать это! Спасибо!

1 Ответ

0 голосов
/ 04 апреля 2019

Приношу свои извинения, поскольку в исходном ответе есть некоторые логические ошибки. Наконец-то у меня было время проверить его

CREATE TABLE #MyTable (workerid int, maindoc varchar(5), subdoc varchar(2), value varchar(3), timestamp varchar(5))

insert #MyTable values 
(1234, 'Doc1', 'A1', 'abc', '11:40'),
(1234, 'Doc1', 'A2', 'def', '11:40'),
(1234, 'Doc1', 'B1', '30' , '11.40'),
(1234, 'Doc1', 'B2', '40' , '11:40'),
(1234, 'Doc1', 'C1', '50' , '11:40'),
(1234, 'Doc1', 'C1', '51' , '11:50'),
(1234, 'Doc1', 'C2', '60' , '11:40'),
(1234, 'Doc1', 'C2', '61' , '11:50'),
(1235, 'Doc1', 'A1', 'fgf', '11:55'),
(1235, 'Doc1', 'A2', 'vbv', '11:55');

В этом подходе мой первый шаг - использовать CTEчтобы получить ValueNumber и взять последнее значение для каждого SubDoc, затем я Pivot значений ....

WITH subDocs AS (
    SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY SubDoc) vn, SubDoc FROM (SELECT DISTINCT SubDoc FROM #MyTable) A
), cte AS (
    SELECT 
        WorkerID, 
        MainDoc, 
        T.SubDoc,
        Value,
        ROW_NUMBER() OVER (PARTITION BY WorkerID, MainDoc, T.SubDoc ORDER BY TimeStamp DESC) AS rn, 
        vn
    FROM #MyTable T
    JOIN subDocs S ON T.subdoc = S.subdoc 
)
SELECT WorkerID, MainDoc, [1] as [Value(1)], [2] as [Value(2)], [3] as [Value(3)], [4] as [Value(4)], [5] as [Value(5)], [6] as [Value(6)]
FROM (
    SELECT WorkerID, Maindoc, vn, Value FROM cte WHERE rn = 1
) Source
PIVOT (
    MAX(Value) FOR vn IN ([1],[2],[3],[4],[5],[6])
) PVT

Но, скорее всего, количество нужных столбцов не является фиксированным, и вам нужно использоватьдинамический SQL, чтобы получить его

DECLARE @SQL NVARCHAR(MAX);
DECLARE @SubDocCount INT
DECLARE @ColumnNames NVARCHAR(MAX)
DECLARE @PivotValues NVARCHAR(MAX)

SELECT TOP 1 @SubDocCount = COUNT(DISTINCT Subdoc) FROM #MyTable

;WITH cols AS (
    SELECT 1 as num
    UNION ALL
    SELECT num + 1
    FROM cols WHERE num < @SubDocCount 
)
SELECT 
    @ColumnNames = STUFF(
             (SELECT ',' + QUOTENAME(CAST(num AS VARCHAR)) + ' AS ' + QUOTENAME('Value' + QUOTENAME(CAST(num AS VARCHAR),'('))
              FROM cols
              FOR XML PATH (''))
             , 1, 1, ''),
    @PivotValues = STUFF(
             (SELECT ',' + QUOTENAME(CAST(num AS VARCHAR)) 
              FROM cols
              FOR XML PATH (''))
             , 1, 1, '')

SET @SQL = N'
    WITH subDocs AS (
        SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY SubDoc) vn, SubDoc FROM (SELECT DISTINCT SubDoc FROM #MyTable) A
    ), cte AS (
        SELECT 
            WorkerID, 
            MainDoc, 
            T.SubDoc,
            Value,
            ROW_NUMBER() OVER (PARTITION BY WorkerID, MainDoc, T.SubDoc ORDER BY TimeStamp DESC) AS rn, 
            vn
        FROM #MyTable T
        JOIN subDocs S ON T.subdoc = S.subdoc 
    )
    SELECT WorkerID, MainDoc, ' + @ColumnNames + '
    FROM (
        SELECT WorkerID, Maindoc, vn, Value FROM cte WHERE rn = 1
    ) Source
    PIVOT (
        MAX(Value) FOR vn IN (' + @PivotValues + ')
    ) PVT'

EXEC (@SQL)

Примечание в вашем примере входных данных есть 3 разных WorkerID, учитывая ожидаемый результат, который я принял за 1224 и 1234 как опечатку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...