2

我正在研究基于 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)
);
4

2 回答 2

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 Fiddle with Demo

一旦你有逻辑下来,然后将其转换为动态 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 |
于 2013-11-13T19:14:31.280 回答
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;
于 2020-12-12T15:02:20.367 回答