简体   繁体   English

如何将 SQL Server 列转换为行?

[英]How to convert SQL Server columns into rows?

I need help to switch columns with rows in SQL.我需要帮助在 SQL 中用行切换列。 Need to turn this:需要转这个:

+------------+------------+-------------+------+
|    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 |      |
|...         |            |             |      |
+------------+------------+-------------+------+

into this:进入这个:

+------------+------------+------------+------------+------------+-----+
| 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 |     |
+------------+------------+------------+------------+------------+-----+

Can someone help me?有人能帮我吗? Should I use PIVOT ?我应该使用PIVOT吗?

EDIT: I've tried using some suggestions like PIVOT and UNPIVOT , but I could not achieve the expected result.编辑:我尝试使用一些建议,如PIVOTUNPIVOT ,但我无法达到预期的结果。

I've tried:我试过了:

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

However with the above query I only managed to get some of what I need,然而,通过上面的查询,我只能得到一些我需要的东西,

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

I need to have production and consumption, all in the same query, but I can only get one of them.我需要生产和消费,都在同一个查询中,但我只能得到其中之一。

Is it possible to put more than one column in PIVOT ?是否可以在PIVOT放置多于一列? I've tried, but unsuccessfully.我试过了,但没有成功。

You can achieve the desired output with dynamic sql, but be aware of performance and security problems (ie SQL injection) of this approach.您可以使用动态 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)

Result:结果:

在此处输入图片说明

Now if you add a column and some more rows:现在,如果您添加一列和更多行:

--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) 

this is the result:这是结果:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM