跨多列的动态数据透视 Table
Dynamic Pivot Table across multiple columns
我是 SQL 的新手,需要一些帮助。我有一个 table 的时间 sheet 数据,每一行都有一个单独的时间 sheet。每次 sheet 都有一个包含 jobcode1 到 jobcode16 的列,它存储一个表示工作代码的字符串。每一个都有对应的 TotalJob1 到 TotalJob16。
我已经成功地在 JobCode1 上创建了一个枢轴,每个 Job 的列和 TotalJob1 的总数没有问题。我用 this 来构建它。
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
我正在努力迭代其他 Job 列并将它们合并成一个大枢纽 table 并希望有人能给我一个指导?
我的想法是尝试重复该步骤 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 | JobCode1 | JobCode2 | JobCode3 | TotalJob1 | TotalJob2 | TotalJob3 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 1 | J1 | J3 | | 10 | 9 | |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 2 | J2 | J1 | J3 | 5 | 5 | 5 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 3 | J2 | | | 6 | 3 | 1 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
我想达到的目标
+-------------+----+----+----+----+----+
| TimesheetID | J1 | J2 | J3 | J4 | J6 |
+-------------+----+----+----+----+----+
| 1 | 10 | | 9 | | |
+-------------+----+----+----+----+----+
| 2 | 5 | 5 | 5 | | |
+-------------+----+----+----+----+----+
| 3 | | 6 | | 3 | 1 |
+-------------+----+----+----+----+----+
它会变得非常复杂,但您可以做的一件事是对数据进行 UNPIVOT,使其看起来像这样:
TimesheetId JobCode JobTotal
1 J1 10
1 J3 9
2 J1 5
....
然后 PIVOT 派生的 table 以获得您想要的结果。
就像提到的 Tab 一样,您可以先对数据进行逆透视,然后再对它进行透视。
您可以使用 CROSS APPLY 和 VALUES 将您的 table 转换为临时文件 table。
SELECT ca.*
INTO #temp
FROM timesheet
CROSS APPLY (VALUES
(TimesheetID, JobCode1, TotalJob1),
(TimesheetID, JobCode2, TotalJob2),
(TimesheetID, JobCode3, TotalJob3)
) ca(TimesheetID, JobCode, TotalJob)
这给你一个 table 喜欢
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
不确定实际数据中是否有空职位代码..但您可以使用上面的 Where ca.JobCode IS NOT NULL
消除它们
然后从临时文件创建动态列字符串 table
DECLARE @JobCodes nvarchar(MAX)
SELECT @JobCodes = COALESCE(@JobCodes + ',','') + QUOTENAME(JobCode)
FROM #temp
GROUP BY JobCode
ORDER BY JobCode
然后构建您的动态枢轴。无需创建全局临时文件 table,只需在数据透视查询中使用之前的相同查询即可。
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
我是 SQL 的新手,需要一些帮助。我有一个 table 的时间 sheet 数据,每一行都有一个单独的时间 sheet。每次 sheet 都有一个包含 jobcode1 到 jobcode16 的列,它存储一个表示工作代码的字符串。每一个都有对应的 TotalJob1 到 TotalJob16。
我已经成功地在 JobCode1 上创建了一个枢轴,每个 Job 的列和 TotalJob1 的总数没有问题。我用 this 来构建它。
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
我正在努力迭代其他 Job 列并将它们合并成一个大枢纽 table 并希望有人能给我一个指导?
我的想法是尝试重复该步骤 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 | JobCode1 | JobCode2 | JobCode3 | TotalJob1 | TotalJob2 | TotalJob3 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 1 | J1 | J3 | | 10 | 9 | |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 2 | J2 | J1 | J3 | 5 | 5 | 5 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 3 | J2 | | | 6 | 3 | 1 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
我想达到的目标
+-------------+----+----+----+----+----+
| TimesheetID | J1 | J2 | J3 | J4 | J6 |
+-------------+----+----+----+----+----+
| 1 | 10 | | 9 | | |
+-------------+----+----+----+----+----+
| 2 | 5 | 5 | 5 | | |
+-------------+----+----+----+----+----+
| 3 | | 6 | | 3 | 1 |
+-------------+----+----+----+----+----+
它会变得非常复杂,但您可以做的一件事是对数据进行 UNPIVOT,使其看起来像这样:
TimesheetId JobCode JobTotal
1 J1 10
1 J3 9
2 J1 5
....
然后 PIVOT 派生的 table 以获得您想要的结果。
就像提到的 Tab 一样,您可以先对数据进行逆透视,然后再对它进行透视。
您可以使用 CROSS APPLY 和 VALUES 将您的 table 转换为临时文件 table。
SELECT ca.*
INTO #temp
FROM timesheet
CROSS APPLY (VALUES
(TimesheetID, JobCode1, TotalJob1),
(TimesheetID, JobCode2, TotalJob2),
(TimesheetID, JobCode3, TotalJob3)
) ca(TimesheetID, JobCode, TotalJob)
这给你一个 table 喜欢
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
不确定实际数据中是否有空职位代码..但您可以使用上面的 Where ca.JobCode IS NOT NULL
然后从临时文件创建动态列字符串 table
DECLARE @JobCodes nvarchar(MAX)
SELECT @JobCodes = COALESCE(@JobCodes + ',','') + QUOTENAME(JobCode)
FROM #temp
GROUP BY JobCode
ORDER BY JobCode
然后构建您的动态枢轴。无需创建全局临时文件 table,只需在数据透视查询中使用之前的相同查询即可。
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