我正在开发基于2列的双动态数据透视图(HardwarePhase& HardwarePhase_Result)。
使用下图中的第一个结果集,是我拥有的原始数据。每组5个项目(在图像中突出显示)基于HardwareTestCaseID进行分组。
图像中的第二个结果集是我从构建此查询的方式得到的当前结果。 理想情况,第二列的结果将是相同的结果,但它会将结果分组。
分组应该基于HardwareTestCaseID,但是,这种情况不会发生。
此处显示了我实际想要的结果。 (应该有多行,但这只是每5个条目应该如何分组)。
这是我目前使用的查询:
注意:@col变量是基于HardwarePhases(P0,M1,M2,M3)列表构建的。
select @query = 'SELECT ' + @colsNames + ',' + @colsResultNames + ', HardwareTestCaseID FROM
(
SELECT HardwarePhase_Result, HardwarePhase, ResultValue, HardwareTestCaseID, HardwareStatus
FROM #temp4
) as x
pivot
(
MAX(ResultValue)
FOR HardwarePhase_Result IN (' + @colsResult + ')
) as p
pivot
(
MAX(HardwareStatus)
FOR HardwarePhase IN (' + @cols + ')
) as p2 ';
使用此表:
create table #temp4
(
HardwarePhase nvarchar(max),
HardwarePhase_Result nvarchar(max),
ResultValue bigint,
HardwareTestCaseID bigint,
HardwareStatus nvarchar(max),
Block nvarchar(max)
);
答案 0 :(得分:3)
我个人会稍微不同,因为你想在两列上进行PIVOT。我会先看看多列中的数据,然后应用PIVOT函数。我还建议您首先编写查询的硬编码版本,然后将其转换为动态SQL - 这样您就可以获得正确的逻辑。
要对数据进行取消操作,我会使用CROSS APPLY,这样您就可以同时将列对转换为行,语法类似于以下内容:
select col, value, HardwareTestCaseID
from temp4
cross apply
(
select HardwarePhase, HardwareStatus union all
select HardwarePhase_Result, cast(ResultValue as varchar(10))
) c (col, value)
见SQL Fiddle with Demo。然后,您的数据格式为:
| COL | VALUE | HARDWARETESTCASEID |
|-----------|-------------|--------------------|
| P0 | Not Started | 365 |
| P0_Result | 1 | 365 |
| M1 | Pass | 365 |
| M1_Result | 1 | 365 |
| M4 | Pass | 365 |
| M4_Result | 1 | 365 |
| M2 | Blocked | 365 |
| M2_Result | 1 | 365 |
然后您只需将数据透视功能应用于数据:
select M1, M2, M3, M4, P0,
M1_Result, M2_Result, M3_Result,
M4_Result, P0_Result,
HardwareTestCaseID
from
(
select col, value, HardwareTestCaseID
from temp4
cross apply
(
select HardwarePhase, HardwareStatus union all
select HardwarePhase_Result, cast(ResultValue as varchar(10))
) c (col, value)
) d
pivot
(
max(value)
for col IN (M1, M2, M3, M4, P0,
M1_Result, M2_Result, M3_Result,
M4_Result, P0_Result)
) piv;
关闭逻辑后,将其转换为动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col)
from temp4
cross apply
(
select HardwarePhase, 1 union all
select HardwarePhase_Result, 2
) c (col, so)
group by col, so
order by so, col
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ' + @cols + ' , HardwareTestCaseID
from
(
select col, value, HardwareTestCaseID
from temp4
cross apply
(
select HardwarePhase, HardwareStatus union all
select HardwarePhase_Result, cast(ResultValue as varchar(10))
) c (col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
execute sp_executesql @query;
见SQL Fiddle with Demo。这个过程得到一个结果:
| M1 | M2 | M3 | M4 | P0 | M1_RESULT | M2_RESULT | M3_RESULT | M4_RESULT | P0_RESULT | HARDWARETESTCASEID |
|---------|---------|---------|---------|-------------|-----------|-----------|-----------|-----------|-----------|--------------------|
| Pass | Blocked | Pass | Pass | Not Started | 1 | 1 | 1 | 1 | 1 | 365 |
| Blocked | Blocked | Blocked | Blocked | Pass | 1 | (null) | 1 | 1 | 1 | 366 |
答案 1 :(得分:1)
--This is Just AWESOME. Simplified it for just one table as it's a much more common case (and could not find anything even close to this elegant after trying for hours)
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(your_key_column)
from YOUR_ORIGINAL_KEY_AND_VALUE_TABLE
group by your_key_column
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT your_row_heading_columns,' + @cols + '
INTO YOUR_NEW_PIVOTED_TABLE
from
(
select your_row_heading_columns,your_key_column,your_value_column
from YOUR_ORIGINAL_KEY_AND_VALUE_TABLE
) x
pivot
(
max(your_value_column)
for your_key_column in (' + @cols + ')
) p '
execute sp_executesql @query;