SQL 将列转置为具有波动行的行

SQL Transpose Columns to Rows with fluctuating Rows

我正在尝试转置视图中的列和行,但是这些行是每周更改的日期,我似乎无法正常运行。

下面是我的;

Date       | Report1 | Report2 |
---------- | ------- | ------- | 
2017-07-01 | N/A     | Yes     |
2017-07-02 | Yes     | Yes     |
2017-07-03 | N/A     | Yes     |
2017-07-04 | Yes     | Yes     |
2017-07-05 | N/A     | Yes     |
2017-07-06 | NULL    | NULL    |
2017-07-07 | N/A     | N/A     |

我希望它看起来像;

Date     | 2017-07-01 | 2017-07-02 | 2017-07-03 | 2017-07-04 | 2017-07-05 | 2017-07-06 | 2017-07-07 |
-------- | ---------- | ---------- | ---------- | ---------- | ---------- | ---------- | ---------- |
Report1  | N/A        | Yes        | N/A        | Yes        | N/A        | Null       | N/A        |
Report2  | Yes        | Yes        | Yes        | Yes        | Yes        | Null       | N/A        |

唯一的问题是日期在滚动,因此列名会发生变化。 *还有更多报告,但为简单起见,2 个就足够了

您实际上需要结合使用 UNPIVOT 和 Dynamic PIVOT

IF (OBJECT_ID('tempdb..#unpvt') IS NOT NULL) DROP TABLE #unpvt;
SELECT Report, Val, [Date]
INTO #unpvt
FROM 
(
    SELECT [Date], [Report1], [Report2]
    FROM YourTable
) p
UNPIVOT
   (Val FOR Report IN ([Report1], [Report2])
)AS unpvt;


DECLARE @cols AS NVARCHAR(MAX);
DECLARE @sql AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ', ' + QUOTENAME([Date])
                   FROM YourTable c
                   FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,2,'');

SET @sql = 'SELECT Report, ' + @cols + ' FROM
            (
                SELECT * FROM #unpvt
            ) x
            PIVOT 
            (
                MAX(Val)
                FOR [Date] in (' + @cols + ')
            ) p ';


EXECUTE(@sql);

以下将动态反透视您的数据,然后 create/execute 动态透视。

使用动态 UNPIVOT,无需指定字段(或 "reports")

此外,使用日期参数(@Date1 和@Date2),您可以指定要透视的所需日期范围

例子

Declare @Date1 varchar(10) = '2017-07-01'
Declare @Date2 varchar(10) = '2017-07-07'

Declare @SQL varchar(max) = '
Declare @XML xml = (Select * from YourTable Where Date Between '''+@Date1+''' and '''+@Date2+''' for XML RAW)

Select *
 From (
        Select Date   = r.value(''@Date'',''Date'')
              ,Item   = attr.value(''local-name(.)'',''varchar(100)'')
              ,Value  = attr.value(''.'',''varchar(max)'') 
         From  @XML.nodes(''/row'') as A(r)
         Cross Apply A.r.nodes(''./@*'') AS B(attr)
         Where attr.value(''local-name(.)'',''varchar(100)'') not in (''Date'')
      ) A
 Pivot (max([Value]) For [Date] in (' + Stuff((Select Distinct ','+QuoteName(Date) 
                                               From  YourTable
                                               Where Date Between @Date1 and @Date2
                                               Order By 1 
                                               For XML Path('')),1,1,'')  + ') ) p'
Exec(@SQL);
--Print @SQL

Returns