Запрос Транспонирование определенных строк в имена столбцов - PullRequest
2 голосов
/ 29 мая 2009

У меня есть пара таблиц, которые выглядят так Таблица 1

user_id   |  name
-------------------------   
x111      |   Smith, James
x112      |   Smith, Jane

и т.д ..

Таблица 2

id    |   code    |    date       |  incident_code    | user_id
-----------------------------------------------------------------
1     |    102008 |   10/20/2008  |    1              | x111
2     |    113008 |   11/30/2008  |    3              | x111
3     |    102008 |   10/20/2008  |    2              | x112
4     |    113008 |   11/30/2008  |    5              | x112 

То, что я хотел бы отобразить, это что-то вроде этого

user_id     |    user_name    |   INCIDENT IN OCT 2008   | INCIDENT IN NOV 2008
------------------------------------------------------------------------------ 
x111        |    Smith, John  |   1                      | 3
x112        |    Smith, Jane  |   2                      | 5

и т.д ..

Код инцидента будет заменен фактическим описанием инцидента, которое находится в другой таблице, но я подумал, что сначала посмотрю, как это будет работать.

Некоторые заголовки столбцов будут статическими, в то время как другие будут создаваться на основе даты. Кто-нибудь знает, как я могу сделать это с помощью SQL Server 2005? Некоторые примеры были бы очень полезны.

Заранее спасибо

Ответы [ 4 ]

2 голосов
/ 30 мая 2009

Вот решение, которое генерирует и запускает динамический SQL с PIVOT:

DECLARE @pivot_list AS VARCHAR(MAX)

--
;
WITH    cols
          AS ( SELECT DISTINCT
                        'INCIDENT IN ' + LEFT(UPPER(CONVERT(VARCHAR, [date], 107)),
                                              3) + ' '
                        + SUBSTRING(UPPER(CONVERT(VARCHAR, [date], 107)), 9, 4) AS col
               FROM     so926209_2
             )
    SELECT  @pivot_list = COALESCE(@pivot_list + ', ', '') + '[' + col + ']'
    FROM    cols

--
DECLARE @template AS VARCHAR(MAX)
SET @template = 'WITH incidents AS (
SELECT  [user_id],
        incident_code,
        ''INCIDENT IN '' + LEFT(UPPER(CONVERT(VARCHAR, [date], 107)), 3)
        + '' '' + SUBSTRING(UPPER(CONVERT(VARCHAR, [date], 107)), 9, 4) AS col
FROM    so926209_2
)
,results AS (
SELECT * FROM incidents PIVOT (MAX(incident_code) FOR col IN ({@pivot_list})) AS pvt
)
SELECT results.[user_id]
    ,so926209_1.[name]
    ,{@select_list}
FROM results INNER JOIN so926209_1 ON so926209_1.[user_id] = results.[user_id]
'

DECLARE @sql AS VARCHAR(MAX)
SET @sql = REPLACE(REPLACE(@template, '{@pivot_list}', @pivot_list), '{@select_list}', @pivot_list)

--PRINT @sql
EXEC (@sql)

Где so926209_1, so926209_2 - ваш стол 1 и стол 2

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

0 голосов
/ 29 мая 2009

Это звучит как задача отчетности. Отчеты, часто называемые с точки зрения базы данных OLAP, Online Aanalytical Processing, имеют тенденцию довольно часто отличаться от «традиционного» доступа к базе данных, OLTP (Online Transaction Processing), в том, что они довольно часто состоят из больших скоплений данных, охватывающих большие периоды времени. Довольно часто вид агрегации вы ищете.

Использование Pivot, как предложил Tetraneutron, будет достаточно для небольших наборов данных. Однако по мере роста объема данных, о которых вам необходимо сообщать, вам может потребоваться что-то более продвинутое. OLAP предоставляется службами аналитики SQL Server (SSAS), доступными в 2005 и 2008 годах. Используя SSAS, вы можете создавать многомерные хранилища данных, которые предварительно агрегируют данные либо из базы данных OLTP напрямую, либо из базы данных промежуточного хранилища данных. Многомерные данные (обычно называемые кубами) предоставляют намного более быстрый способ доступа к типу данных, которые вы можете получить из Pivot, не влияя на производительность стандартной обработки транзакций в вашей базе данных OLTP.

Если у вас есть более чем небольшой объем данных, по которым необходимо составить отчет, я рекомендую вам воспользоваться службами SQL Server Analysis Services 2005, OLAP, Cubes и MDX (многомерные расширения для T-SQL). кривая для настройки куба OLAP, но как только он настроен, преимущества его наличия могут быть огромными, если у вас есть значительные потребности в отчетности.

0 голосов
/ 29 мая 2009

Такой запрос будет работать:

select
    u.User_id,
    u.Name,
    Okt2008Sum = sum(case when i.date between 
        '2008-10-01' and '2008-11-01' then 1 else 0 end),
    Nov2008Sum = sum(case when i.date between 
        '2008-11-01' and '2008-12-01'then 1 else 0 end)
from #incidents i
inner join #users u on i.user_id = u.user_id
group by u.user_id, u.name

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

create table #months (
    MonthName varchar(25),
    StartDate datetime
)

insert into #months values ('Okt2008','2008-10-01')
insert into #months values ('Nov2008','2008-11-01')

declare @query varchar(8000)
select @query = 'select u.User_id, u.Name '

select @query = @query + ', ' + MonthName + 
    ' = sum(case when i.date between ''' + cast(StartDate as varchar) + 
    ''' and ''' + cast(dateadd(m,1,StartDate) as varchar) + 
    ''' then 1 else 0 end) '
from #Months

select @query = @query + '
    from #incidents i
    inner join #users u on i.user_id = u.user_id
    group by u.user_id, u.name'

exec (@query)
0 голосов
/ 29 мая 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...