Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SQL Server中将数据行转换为具有不同列的单行_Sql_Sql Server - Fatal编程技术网

如何在SQL Server中将数据行转换为具有不同列的单行

如何在SQL Server中将数据行转换为具有不同列的单行,sql,sql-server,Sql,Sql Server,目前我有来自temp的数据,我从其他表中提取数据。临时表格式如下所示 WorkerID MainDoc SubDoc Value TimeStamp -------- -------- --------- ----- --------- 1224 Doc1 A1 abc 11:40 1234 Doc1 A2 def 11:40 1224 Doc1 B1

目前我有来自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  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
当WorkerID相同且格式如下时,我需要将这些行转换为具有最新时间戳值的单行

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  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
因此,我如何着手做这件事!谢谢

我很抱歉,因为原始答案有一些逻辑错误,最后我可以有时间来测试它

在这种方法中,我的第一步是使用CTE获取ValueNumber,并获取每个子文档的最后一个值,然后我将这些值作为轴心

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为打字错误的预期结果,google CROSSAPPLY您的时间戳值不一致。前两个值使用冒号,其他值使用点分隔小时和分钟。应该先纠正吗?或者它应该按原样工作?您使用的是哪个SQL版本?对不起,时间戳,我已经对它进行了更改,目前正在使用MS SQL2014@VirVir对不起,我的原始答案,我无法测试它,它充满了错误,理应被否决,现在已修复。。。