如何将SQL Server列转换为行?

问题描述 投票:-7回答:1

我需要帮助在SQL中使用行切换列。需要转此:

+------------+------------+-------------+------+
|    Date    | Production | Consumption | .... |
+------------+------------+-------------+------+
| 2017-01-01 |        100 |        1925 |      |
| 2017-01-02 |        200 |        2005 |      |
| 2017-01-03 |        150 |        1998 |      |
| 2017-01-04 |        250 |        2200 |      |
| 2017-01-05 |         30 |         130 |      |
|...         |            |             |      |
+------------+------------+-------------+------+

进入这个:

+------------+------------+------------+------------+------------+-----+
| 01-01-2017 | 02-01-2017 | 03-01-2017 | 04-01-2017 | 05-01-2017 | ... |
+------------+------------+------------+------------+------------+-----+
|        100 |        200 |        150 |        250 |         30 |     |
|       1925 |       2005 |       1998 |       2200 |        130 |     |
+------------+------------+------------+------------+------------+-----+

有人能帮我吗?我应该使用PIVOT吗?

编辑:我已经尝试使用像PIVOTUNPIVOT这样的建议,但我无法达到预期的结果。

我试过了:

SELECT *
FROM (
    SELECT date, Consumption
    FROM Energy
    where date < '2017-02-01'
) r
pivot (sum(Consumption) for date in ([2017-01-01],[2017-01-02],[2017-01-03]....)) c
order by 1

但是通过上面的查询我只能设法获得我需要的一些东西,

+------------+------------+------------+------------+------------+-----+
| 01-01-2017 | 02-01-2017 | 03-01-2017 | 04-01-2017 | 05-01-2017 | ... |
+------------+------------+------------+------------+------------+-----+
|        100 |        200 |        150 |        250 |         30 |     |
+------------+------------+------------+------------+------------+-----+

我需要生产和消费,所有都在同一个查询中,但我只能得到其中一个。

是否可以在PIVOT中放置多个列?我试过了,但没有成功。

sql sql-server tsql pivot
1个回答
0
投票

您可以使用动态sql实现所需的输出,但要注意此方法的性能和安全性问题(即SQL注入)。

--create test table 
CREATE TABLE dbo.Test ( 
      [Date]      date 
    , Production  int 
    , Consumption int 
) 

--populate test table with values 
insert into dbo.Test 
values 
 ('2017-01-01', 100, 1925) 
,('2017-01-02', 200, 2005) 
,('2017-01-03', 150, 1998) 
,('2017-01-04', 250, 2200) 
,('2017-01-05',  30,  130) 

--table variable that will hold the names of all columns to pivot 
declare @columNames table (ColumnId int identity (1,1), ColumnName varchar(255)) 
--variable that will hold the total number of columns to pivot 
declare @columnCount int 
--variable that will be used to run through the columns to pivot 
declare @counter int = 1 
--this variable holds all column names 
declare @headers nvarchar(max) = '' 
--this variable contains the TSQL dinamically generated 
declare @sql nvarchar(max) = '' 

--populate list of columns to pivot 
insert into @columNames 
select COLUMN_NAME 
from INFORMATION_SCHEMA.COLUMNS 
where 
        TABLE_NAME   = 'test' 
    and TABLE_SCHEMA = 'dbo' 
    and COLUMN_NAME  <>'date' 

--populate column total counter 
select @columnCount = count(*) from @columNames 

--populate list of headers of the result table 
select @headers = @headers + ', ' + quotename([Date]) 
from dbo.Test 

set @headers = right(@headers, len(@headers) - 2) 

--run through the table containing the columns names and generate the dynamic sql query 
while @counter <= @columnCount 
begin 
    select @sql = @sql + ' select piv.* from (select [Date], ' 
        + quotename(ColumnName) + ' from dbo.Test) p pivot (max(' 
        + quotename(ColumnName) + ') for [Date] in (' 
        + @headers + ') ) piv ' 
    from @columNames where ColumnId = @counter 

    --add union all except when we are concatenating the last pivot statement
    if @counter < @columnCount 
        set @sql = @sql + ' union all' 

    --increment counter
    set @counter = @counter + 1 
end 

--execute the dynamic query
exec (@sql)

结果:

enter image description here

现在,如果您添加一列和更多行:

--create test table 
CREATE TABLE [dbo].[Test] ( 
      [Date]      date 
    , Production  int 
    , Consumption int 
    , NewColumn   int 
) 

--populate test table with values 
insert into [dbo].[Test] 
values 
 ('2017-01-01', 100, 1925 , 10) 
,('2017-01-02', 200, 2005, 20) 
,('2017-01-03', 150, 1998, 30) 
,('2017-01-04', 250, 2200, 40) 
,('2017-01-05', 30, 130  , 50) 
,('2017-01-06', 30, 130  , 60) 
,('2017-01-07', 30, 130  , 70) 

这是结果:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.