Sql 跨多列的动态数据透视表

Sql 跨多列的动态数据透视表,sql,sql-server,tsql,dynamic,pivot,Sql,Sql Server,Tsql,Dynamic,Pivot,我是SQL的新手,需要一些帮助。我有一个时间表数据表,每行有一个单独的时间表。每个时间表都有一个包含jobcode1到jobcode16的列,该列存储指示作业代码的字符串。其中每个都有对应的TotalJob1到TotalJob16 我已经成功地在JobCode1上创建了一个轴心,每个Job都有一个列,TotalJob1的总数也没有问题。我曾经建造过它 DECLARE @DynamicPivotQuery AS NVARCHAR(MAX) DECLARE @ColumnName AS NVARCH

我是SQL的新手,需要一些帮助。我有一个时间表数据表,每行有一个单独的时间表。每个时间表都有一个包含jobcode1到jobcode16的列,该列存储指示作业代码的字符串。其中每个都有对应的TotalJob1到TotalJob16

我已经成功地在JobCode1上创建了一个轴心,每个Job都有一个列,TotalJob1的总数也没有问题。我曾经建造过它

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)

SELECT @ColumnName = ISNULL(@ColumnName + ',','') + QUOTENAME(TS_Job1Code)
FROM (SELECT DISTINCT TS_Job1Code FROM 
dbo.timesheetData) as timesheetdata

SET @DynamicPivotQuery = 
N'SELECT VolumeID, ' + @ColumnName + '
FROM dbo.timesheetData
PIVOT(SUM(TS_TotalJob1)
FOR TS_Job1Code IN (' + @ColumnName + ')) AS PVTTable'

EXEC sp_executesql @DynamicPivotQuery
我正在努力迭代其他作业列并将它们合并到一个大数据透视表中,希望有人能给我一个指针

我的想法是尝试重复这一步16次,但我认为这甚至都不接近正确的方式

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @N AS INT
DECLARE @NCHAR AS NVARCHAR(MAX)
SET @N = 1

WHILE @N < 17
BEGIN
SET @NCHAR = CAST(@N as VARCHAR)
SELECT @ColumnName = ISNULL(@ColumnName + ',','') + QUOTENAME(('TS_Job' + 
@NCHAR + 'Code'))
FROM (SELECT DISTINCT ('TS_Job' + @NCHAR + 'Code') FROM 
dbo.timesheetData) as timesheetdata

SET @DynamicPivotQuery = 
N'SELECT ' + @ColumnName + '
FROM dbo.timesheetData
PIVOT(SUM(TS_TotalJob' + @NCHAR + ')
    FOR TS_Job' + @NCHAR + 'Code IN (' + @ColumnName + ')) AS PVTTable'

EXEC sp_executesql @DynamicPivotQuery
SET @N = @N + 1
END
EXEC sp_executesql @SQL
我想要达到的目标

+-------------+----+----+----+----+----+
| TimesheetID | J1 | J2 | J3 | J4 | J6 |
+-------------+----+----+----+----+----+
| 1           | 10 |    | 9  |    |    |
+-------------+----+----+----+----+----+
| 2           | 5  | 5  | 5  |    |    |
+-------------+----+----+----+----+----+
| 3           |    | 6  |    | 3  | 1  |
+-------------+----+----+----+----+----+

这将变得非常复杂,但您可以做的一件事是取消对数据的归档,使其看起来像这样:

TimesheetId    JobCode    JobTotal
1              J1         10
1              J3         9
2              J1         5
....

然后透视该派生表以获得所需的结果。

就像前面提到的选项卡一样,您可以先取消透视数据,然后再透视数据

您可以使用“交叉应用”和“值”将表取消填充到临时表中

SELECT ca.* 
INTO #temp
FROM timesheet
CROSS APPLY (VALUES
    (TimesheetID, JobCode1, TotalJob1), 
    (TimesheetID, JobCode2, TotalJob2), 
    (TimesheetID, JobCode3, TotalJob3)
) ca(TimesheetID, JobCode, TotalJob)
这给你一张像这样的桌子

TimesheetID JobCode TotalJob
----------- ------- -----------
1           J1      10
1           J3      9
1           NULL    NULL
2           J2      5
2           J1      5
2           J3      5
3           J2      6
3           NULL    3
3           NULL    1
不确定实际数据中是否有空作业代码。。但是您可以使用上面的ca.JobCode不为NULL的
来消除它们

然后从临时表中创建动态列字符串

DECLARE @JobCodes nvarchar(MAX)
SELECT  @JobCodes = COALESCE(@JobCodes + ',','') + QUOTENAME(JobCode)
FROM       #temp
GROUP BY JobCode
ORDER BY JobCode
然后构建您的动态轴心。不要创建全局临时表,只需在pivot查询中使用前面的相同查询即可

DECLARE @Sql nvarchar(max)
SET @Sql = N'
    SELECT TimeSheetID,' + @JobCodes 
    + 'FROM (
       SELECT ca.* 
       FROM timesheet
       CROSS APPLY (VALUES
          (TimesheetID, JobCode1, TotalJob1), 
          (TimesheetID, JobCode2, TotalJob2), 
          (TimesheetID, JobCode3, TotalJob3)
       ) ca(TimesheetID, JobCode, TotalJob)
    ) t
    PIVOT (
       SUM(TotalJob)
       FOR JobCode IN (' + @JobCodes + ')
    ) p'

EXEC sp_executesql @Sql

您希望得到的结果是什么?要么16次硬编码,要么您需要创建一个
光标
选择所有列的名称,
TS_Job1Code,TS_Job2Code等
,然后在光标体中创建
动态SQL查询
。性能方面并没有那么差,因为它只会迭代16次,而您只会使用游标来创建动态SQL。另一方面,在查询中有16个
PIVOT
,需要检查在您的情况下它的性能如何。我不确定你是否能以其他方式实现你所需要的。可能是@TabAlleman的复制品我已经修改了原来的问题。谢谢你的回复,太棒了!谢谢你,这对我有用。再次感谢您抽出时间回复,我非常感谢。
DECLARE @Sql nvarchar(max)
SET @Sql = N'
    SELECT TimeSheetID,' + @JobCodes 
    + 'FROM (
       SELECT ca.* 
       FROM timesheet
       CROSS APPLY (VALUES
          (TimesheetID, JobCode1, TotalJob1), 
          (TimesheetID, JobCode2, TotalJob2), 
          (TimesheetID, JobCode3, TotalJob3)
       ) ca(TimesheetID, JobCode, TotalJob)
    ) t
    PIVOT (
       SUM(TotalJob)
       FOR JobCode IN (' + @JobCodes + ')
    ) p'

EXEC sp_executesql @Sql