动态转置列和行

时间:2018-04-30 10:11:29

标签: sql-server sql-server-2008 tsql pivot

我试图使用类似主题的信息,但仍无法应对。

我的数据是这样的:

+------------+--------------+--------+--------+------------+
|    date    | business_day | total  | number | number_2   |
+------------+--------------+--------+--------+------------+
| 2018-04-03 |            1 | 325857 |      0 |      888   |
| 2018-04-04 |            2 | 196308 |      2 |      829   |
| 2018-04-05 |            3 | 434970 |      1 |      661   |
| 2018-04-06 |            4 | 665941 |      1 |     1135   |
| 2018-04-09 |            5 | 589334 |      0 |      837   |
+------------+--------------+--------+--------+------------+  

如果行数可以是动态的(在这种情况下列号为no),我如何转置它,最终结果应如下所示:

+--------------+------------+------------+------------+------------+--------------+
|     date     | 2018-04-03 | 2018-04-04 | 2018-04-05 | 2018-04-06 | 2018-04-09   |
+--------------+------------+------------+------------+------------+--------------+
| business_day |          1 |          2 |          3 |          4 |          5   |
| total        |     325857 |     196308 |     434970 |     665941 |     589334   |
| number       |          0 |          2 |          1 |          1 |          0   |
| number_2     |        888 |        829 |        661 |       1135 |        837   |
+--------------+------------+------------+------------+------------+--------------+

你能帮我吗?

1 个答案:

答案 0 :(得分:0)

如果您需要一个自动为所有Date值创建所有列的动态查询,您可以使用动态SQL,但要注意此方法的安全性问题(SQL注入等)!

以下示例脚本可动态生成包含Date的所有列的查询:

if OBJECT_ID('Test') is not null
    drop table [dbo].[Test]

CREATE TABLE [dbo].[Test]([date] datetime, business_day int, total int, number int, number_2 int) 

insert into [dbo].[Test] select '2018-04-03', 1, 325857, 0, 888 
insert into [dbo].[Test] select '2018-04-04', 2, 196308, 2, 829 
insert into [dbo].[Test] select '2018-04-05', 3, 434970, 1, 661 
insert into [dbo].[Test] select '2018-04-06', 4, 665941, 1, 1135 
insert into [dbo].[Test] select '2018-04-09', 5, 589334, 0, 837 

declare @dates nvarchar(max)='' --this variable holds all the dates that will become column names
declare @sql nvarchar(max)=''   --this variable contains the TSQL dinamically generated

select @dates = @dates +  ', [' + CONVERT(char(10), [date],126)+  ']' from [dbo].[Test] 
set @dates = RIGHT(@dates, len(@dates)-2)

set @sql = @sql + 'select col as [date], ' + @dates
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [date] , col,val,ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + '     VALUES (''business_day'',business_day, 1), '
set @sql = @sql + '            (''total'',total, 2), '
set @sql = @sql + '            (''number'',number, 3), '
set @sql = @sql + '            (''number_2'',number_2, 4) '
set @sql = @sql + ' )CS (COL,VAL,ORD) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [Date] in (' + @dates + ') ) piv '
set @sql = @sql + 'order by ord'

exec(@sql)

以下是本声明的结果:

enter image description here