Сводка фиксированной таблицы с несколькими столбцами в sql server

У меня есть таблица, которую мне нужно развернуть для служб отчетности:

DateCreated Rands   Units   Average Price   Success %   Unique Users
-------------------------------------------------------------------------
2013-08-26  0       0       0               0              0
2013-08-27  0       0       0               0              0
2013-08-28  10      2       5               100            1
2013-08-29  12      1       12              100            1
2013-08-30  71      9       8               100            1
2013-08-31  0       0       0               0              0
2013-09-01  0       0       0               0              0

Другими словами, мне нужны ранды, единицы, средняя цена и т. Д. В строках, а даты - в столбцах.

Я читал различные примеры, но, похоже, я просто не могу понять это правильно. Любая помощь приветствуется!


person nicV    schedule 02.09.2013    source источник


Ответы (2)


Этот будет делать то, что вы хотите, но вы должны указать все даты

select
   c.Name,
   max(case when t.DateCreated = '2013-08-26' then c.Value end) as [2013-08-26],
   max(case when t.DateCreated = '2013-08-27' then c.Value end) as [2013-08-27],
   max(case when t.DateCreated = '2013-08-28' then c.Value end) as [2013-08-28],
   max(case when t.DateCreated = '2013-08-29' then c.Value end) as [2013-08-29],
   max(case when t.DateCreated = '2013-08-30' then c.Value end) as [2013-08-30],
   max(case when t.DateCreated = '2013-08-31' then c.Value end) as [2013-08-31],
   max(case when t.DateCreated = '2013-09-01' then c.Value end) as [2013-09-01]
from test as t
   outer apply (
       select 'Rands', Rands union all
       select 'Units', Units union all
       select 'Average Price', [Average Price] union all
       select 'Success %', [Success %] union all
       select 'Unique Users', [Unique Users]
   ) as C(Name, Value)
group by c.Name

Вы можете создать для этого динамический SQL, примерно так:

declare @stmt nvarchar(max)

select @stmt = isnull(@stmt + ',', '') + 
    'max(case when t.DateCreated = ''' + convert(nvarchar(8), t.DateCreated, 112) + ''' then c.Value end) as [' + convert(nvarchar(8), t.DateCreated, 112) + ']'
from test as t

select @stmt = '
   select
       c.Name, ' + @stmt + ' from test as t
   outer apply (
       select ''Rands'', Rands union all
       select ''Units'', Units union all
       select ''Average Price'', [Average Price] union all
       select ''Success %'', [Success %] union all
       select ''Unique Users'', [Unique Users]
   ) as C(Name, Value)
   group by c.Name'

exec sp_executesql @stmt = @stmt
person Roman Pekar    schedule 02.09.2013
comment
+1, вам понадобится GROUP BY c.Name, а вот демонстрация скрипта sql, если вы хотите его использовать. - person Mahmoud Gamal; 02.09.2013
comment
@MahmoudGamal спасибо, что напомнили о group by - легко что-то пропустить, если не тестируешь запросы :) - person Roman Pekar; 02.09.2013
comment
Спасибо! Это не совсем то, что мне нужно (я мог бы быть более ясным в вопросе), но я думаю, что это поставит меня на правильный путь! Edit - sql fiddle, не могу поверить, что не знал об этом изумлении! - person nicV; 02.09.2013

Я решил это в конце концов, используя динамический sql, очень похожий на отмеченный ответ. Я не смог найти способ сделать это без динамического sql. Даты должны быть в порядке, и последние 7 дней, они также должны были использовать названия дней недели (которые я не указывал в вопросе).

Самым большим изменением, которое мне нужно было сделать, было преобразование переменной таблицы во временную таблицу. Это связано с тем, что динамические операторы sql выполняются в другом контексте и не знают ни о каких переменных, которые вы создали.

В конце концов, я совершенно сбился с пути, пытаясь использовать PIVOT, и APPLY следует использовать в ситуациях, когда существует более одного "типа" значения.

Я включил свое решение ниже, так как оно может помочь кому-то, у кого есть аналогичная проблема:

CREATE TABLE #SummaryTable
(
    [DateCreated] DATE UNIQUE,
    [Rands] DECIMAL,
    [Units] INT,
    [Average Price] DECIMAL,
    [Success %] INT,
    [Unique Users] INT
);

--Code to fill table

declare @stmt nvarchar(max)

select @stmt = isnull(@stmt + ',', '') + 
    'max(case when t.DateCreated = ''' + convert(nvarchar(16), t.DateCreated, 126)
 + ''' then c.Value end) as [' + left(datename(dw, t.DateCreated),3) + ']'
from #SummaryTable as t

select @stmt = '
   select
       c.Name, ' + @stmt + ' from #SummaryTable as t
   outer apply (
       select ''Rands'', Rands union all
       select ''Units'', Units union all
       select ''Average Price'', [Average Price] union all
       select ''Success'', [Success %] union all
       select ''Unique Users'', [Unique Users]
   ) as C(Name, Value)
   group by c.Name'

exec(@stmt)
person nicV    schedule 03.09.2013