Как преобразовать столбцы SQL Server в строки? - PullRequest
0 голосов
/ 22 февраля 2019

Мне нужна помощь для переключения столбцов со строками в 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?

РЕДАКТИРОВАТЬ: я пытался использовать некоторые предложения, такие как PIVOT и UNPIVOT, но я не смог достичь ожидаемого результата.

Я пытался:

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?Я пытался, но безуспешно.

1 Ответ

0 голосов
/ 12 марта 2019

Вы можете достичь желаемого результата с помощью динамического 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

...