TSQL数据透视问题-寻找更好的方法
这是一个与T-SQL相关的问题。我正在使用SQL Server 2012 我有一张这样的桌子: 我希望有这样的输出: 说明: 对于每个员工,将有一行。员工有一项或多项任务。批次Id指定了这一点。根据批次Id,列名将更改(例如国家1、国家2等) 迄今为止的做法: 按如下方式取消对源表的透视:TSQL数据透视问题-寻找更好的方法,tsql,sql-server-2012,pivot,dynamic-sql,Tsql,Sql Server 2012,Pivot,Dynamic Sql,这是一个与T-SQL相关的问题。我正在使用SQL Server 2012 我有一张这样的桌子: 我希望有这样的输出: 说明: 对于每个员工,将有一行。员工有一项或多项任务。批次Id指定了这一点。根据批次Id,列名将更改(例如国家1、国家2等) 迄今为止的做法: 按如下方式取消对源表的透视: select EmpId, 'Country ' + cast(BatchId as varchar) as [ColumnName], Country as [ColumnValue
select
EmpId, 'Country ' + cast(BatchId as varchar) as [ColumnName],
Country as [ColumnValue]
from
SourceTable
UNION
select
EmpId, 'Pass ' + cast(BatchId as varchar) as [ColumnName],
Pass as [ColumnValue]
from
SourceTable
它以行的形式给出每列的值。然后,可以旋转此结果以获得所需的输出
问题:
- 有更好的方法吗李>
- 目前,我知道将有固定数量的批次,但是,对于未来,如果我想使旋转部件动态化,最好的方法是什么李>
- 使用SSIS或SSRS之类的工具,动态处理枢轴是否更容易李>
DECLARE @cols NVARCHAR(MAX),
@sql NVARCHAR(MAX) = '';
;WITH cte(col_name, rn) AS(
SELECT DISTINCT col_name = col_name + CAST(BatchId AS VARCHAR(10)),
rn = ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY BatchId)
FROM SourceTable
CROSS APPLY (VALUES ('Country', Country), ('Pass', Pass)) AS c(col_name, val)
)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(col_name)
FROM cte
ORDER BY rn /* If column order is important for you */
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SET @sql =
N';WITH cte AS
(
SELECT EmpId, col_name = col_name + CAST(BatchId AS VARCHAR(10)), val
FROM SourceTable
CROSS APPLY (VALUES (''Country'', Country), (''Pass'', Pass)) AS c(col_name, val)
)
SELECT *
FROM cte
PIVOT
(
MAX(val)
FOR col_name IN (' + @cols + ')
) piv';
EXEC(@sql);
警告:我假设Country和Pass列不为NULL
有许多可能的解决方案可以实现您想要的(在多列上搜索动态轴心)
DECLARE @cols NVARCHAR(MAX),
@sql NVARCHAR(MAX) = '';
;WITH cte(col_name, rn) AS(
SELECT DISTINCT col_name = col_name + CAST(BatchId AS VARCHAR(10)),
rn = ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY BatchId)
FROM SourceTable
CROSS APPLY (VALUES ('Country', Country), ('Pass', Pass)) AS c(col_name, val)
)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(col_name)
FROM cte
ORDER BY rn /* If column order is important for you */
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SET @sql =
N';WITH cte AS
(
SELECT EmpId, col_name = col_name + CAST(BatchId AS VARCHAR(10)), val
FROM SourceTable
CROSS APPLY (VALUES (''Country'', Country), (''Pass'', Pass)) AS c(col_name, val)
)
SELECT *
FROM cte
PIVOT
(
MAX(val)
FOR col_name IN (' + @cols + ')
) piv';
EXEC(@sql);
警告:我假设Country和Pass列不为NULL
有许多可能的解决方案可以实现您想要的(在多列上搜索动态轴心)
DECLARE @cols NVARCHAR(MAX),
@sql NVARCHAR(MAX) = '';
;WITH cte(col_name, rn) AS(
SELECT DISTINCT col_name = col_name + CAST(BatchId AS VARCHAR(10)),
rn = ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY BatchId)
FROM SourceTable
CROSS APPLY (VALUES ('Country', Country), ('Pass', Pass)) AS c(col_name, val)
)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(col_name)
FROM cte
ORDER BY rn /* If column order is important for you */
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SET @sql =
N';WITH cte AS
(
SELECT EmpId, col_name = col_name + CAST(BatchId AS VARCHAR(10)), val
FROM SourceTable
CROSS APPLY (VALUES (''Country'', Country), (''Pass'', Pass)) AS c(col_name, val)
)
SELECT *
FROM cte
PIVOT
(
MAX(val)
FOR col_name IN (' + @cols + ')
) piv';
EXEC(@sql);
警告:我假设Country和Pass列不为NULL
有许多可能的解决方案可以实现您想要的(在多列上搜索动态轴心)
DECLARE @cols NVARCHAR(MAX),
@sql NVARCHAR(MAX) = '';
;WITH cte(col_name, rn) AS(
SELECT DISTINCT col_name = col_name + CAST(BatchId AS VARCHAR(10)),
rn = ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY BatchId)
FROM SourceTable
CROSS APPLY (VALUES ('Country', Country), ('Pass', Pass)) AS c(col_name, val)
)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(col_name)
FROM cte
ORDER BY rn /* If column order is important for you */
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SET @sql =
N';WITH cte AS
(
SELECT EmpId, col_name = col_name + CAST(BatchId AS VARCHAR(10)), val
FROM SourceTable
CROSS APPLY (VALUES (''Country'', Country), (''Pass'', Pass)) AS c(col_name, val)
)
SELECT *
FROM cte
PIVOT
(
MAX(val)
FOR col_name IN (' + @cols + ')
) piv';
EXEC(@sql);
警告:我假设Country和Pass列不为NULL
在SQL中完成它
让SSR使用矩阵为您完成工作。它将为您提供数据透视,而无需创建动态SQL来处理需要了解所有列的可怕限制
对于数据,将EMP ID作为行组,PASS作为列组
在SQL中执行此操作
让SSR使用矩阵为您完成工作。它将为您提供数据透视,而无需创建动态SQL来处理需要了解所有列的可怕限制
对于数据,将EMP ID作为行组,PASS作为列组
在SQL中执行此操作
让SSR使用矩阵为您完成工作。它将为您提供数据透视,而无需创建动态SQL来处理需要了解所有列的可怕限制
对于数据,将EMP ID作为行组,PASS作为列组
在SQL中执行此操作
让SSR使用矩阵为您完成工作。它将为您提供数据透视,而无需创建动态SQL来处理需要了解所有列的可怕限制
对于数据,将EMP ID作为行组,PASS作为列组
您做得很好,取消PIVOT PIVOT子句。如果不知道批处理的确切数量,可以使用动态sql。搜索动态数据透视。这是标准方式。你得到了最大批号,并为此构造了pivot语句。这里的最大循环和游标是最糟糕的解决方案。添加了+1以抵消那些没有好理由(如果他们有好的理由,他们可能会说)否决投票的混蛋。你做得对,取消pivot pivot子句。如果不知道批处理的确切数量,可以使用动态sql。搜索动态数据透视。这是标准方式。你得到了最大批号,并为此构造了pivot语句。这里的最大循环和游标是最糟糕的解决方案。添加了+1以抵消那些没有好理由(如果他们有好的理由,他们可能会说)否决投票的混蛋。你做得对,取消pivot pivot子句。如果不知道批处理的确切数量,可以使用动态sql。搜索动态数据透视。这是标准方式。你得到了最大批号,并为此构造了pivot语句。这里的最大循环和游标是最糟糕的解决方案。添加了+1以抵消那些没有好理由(如果他们有好的理由,他们可能会说)否决投票的混蛋。你做得对,取消pivot pivot子句。如果不知道批处理的确切数量,可以使用动态sql。搜索动态数据透视。这是标准方式。你得到了最大批号,并为此构造了pivot语句。最大循环和游标是这里最糟糕的解决方案。添加了+1以抵消那些没有好理由(如果他们有好的理由,他们可能会说)否决投票的混蛋。谢谢汉诺威Fist。我打算用SSRS解决这个问题@你的答案也很完美。不过,我只能选择一个可以接受的答案,所以很遗憾,我不能接受你的答案。谢谢汉诺威。我打算用SSRS解决这个问题@你的答案也很完美。不过,我只能选择一个可以接受的答案,所以很遗憾,我不能接受你的答案。谢谢汉诺威。我打算用SSRS解决这个问题@你的答案也很完美。不过,我只能选择一个可以接受的答案,所以很遗憾,我不能接受你的答案。谢谢汉诺威。我打算用SSRS解决这个问题@你的答案也很完美。然而,我只能选择一个可以接受的答案,所以很遗憾,我不能接受你的答案。