2014-01-09 3 views
0

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

В моих данных содержатся записи о посещениях клиентов, которые были у клиента. Некоторые клиенты будут видеть нас только один раз, а некоторые будут видеть нас много раз за тот же промежуток времени, поэтому у нас нет способа предсказать, сколько посещений на одного клиента у нас будет за данный период времени. Примечание ID 10219 имеет только одно посещение, 5180 имеет 3 и есть много для 5199.

ID  Task    Visit Date  RF Score PF Score 
10219 Follow Up Visit  12/26/2013  1   6 
5180 Initial Visit  6/9/2011  3   9 
5180 Follow Up Visit  7/8/2011  3   10 
5180 Follow Up Visit  9/2/2011  1   10 
5199 Follow Up Visit  9/15/2011  2   7 
5199 Follow Up Visit  9/8/2011  5   6 
5199 Follow Up Visit  10/27/2011  4   7 
5199 Follow Up Visit  10/20/2011  2   4 
5199 Follow Up Visit  10/13/2011  4   8 
5199 Follow Up Visit  11/17/2011  3   4 
5199 Follow Up Visit  11/10/2011  2   5 
5199 Follow Up Visit  11/3/2011  3   3 

с данными, структурированными, как это делает кто-то знает, как преобразовать эти строки в столбцы динамически, даже если я не знаю, сколько столбцов потребуется?

EDIT: конечный результат должен выглядеть следующим образом:

ID   Task1    Visit Date1  RF Score1 PF Score1 Task2    Visit Date2  RF Score2 PF Score2 Task3    Visit Date3  RF Score3 PF Score3 
    5180  Initial Visit   6/9/2011  3   9   Follow Up Visit  7/8/2011  3   10   Follow Up Visit  9/2/2011  1   10 
+0

Что вы хотите, чтобы конечный результат выглядел? – Taryn

+0

Я отредактировал OP, чтобы включить эту деталь. – Baub

+0

Зачем вам нужен этот тип PIVOT в SQL? Не можете ли вы просто вернуть результат клиенту, заказанному по ID, дате, и продолжать идти горизонтально, пока не нажмете новый идентификатор? –

ответ

2

solution that you link to будет работать для вашего случая, но вы должны настроить его немного, потому что вы хотите, чтобы повернуть на несколько столбцов данных. Так как вам нужно развернуть несколько столбцов, вам сначала нужно будет отключить столбцы Visit Date, Task, Rf Score и Pf Score в несколько строк, а затем применить функцию поворота. Помимо процесса поиска, я бы также предложил использовать windowing function, например row_number, для создания уникальной последовательности для каждого id с датой.

Вы начнёте свой запрос, используя следующие:

select id, task, [visit date], [rf score], [pf score], 
    row_number() over(partition by id 
        order by [visit date]) seq 
from yourtable 

См SQL Fiddle with Demo. Это создает число, которое будет использоваться для связывания каждого значения в Visit Date, Task, Rf Score и Pf Score с фактическим номером посещения.

Как только у вас есть номер этой строки, вы захотите отключить несколько столбцов в несколько строк данных. Существует несколько способов сделать это, включая использование функции univot. Но так как вы используете SQL Server 2008R2, вы можете использовать CROSS APPLY с VALUES:

select id, 
    col = col + cast(seq as varchar(10)), 
    value 
from 
(
    select id, task, [visit date], [rf score], [pf score], 
    row_number() over(partition by id 
         order by [visit date]) seq 
    from yourtable 
) d 
cross apply 
(
    values 
    ('VisitDate', convert(varchar(10), [visit date], 120)), 
    ('Task', [task]), 
    ('RfScore', cast([rf score] as varchar(10))), 
    ('PfScore', cast([pf score] as varchar(10))) 
) c (col, value) 

См SQL Fiddle with Demo. Ваши данные теперь в формате, который может быть легко повернуто:

| ID |  COL |   VALUE | 
|-------|------------|-----------------| 
| 5180 | VisitDate1 |  2011-06-09 | 
| 5180 |  Task1 | Initial Visit | 
| 5180 | RfScore1 |    3 | 
| 5180 | PfScore1 |    9 | 
| 5180 | VisitDate2 |  2011-07-08 | 
| 5180 |  Task2 | Follow Up Visit | 
| 5180 | RfScore2 |    3 | 
| 5180 | PfScore2 |    10 | 

код, когда PIVOT добавляется willbe:

select id, 
    VisitDate1, Task1, RfScore1, PfScore1, 
    VisitDate2, Task2, RfScore2, PfScore2, 
    VisitDate3, Task3, RfScore3, PfScore3, 
    VisitDate4, Task4, RfScore4, PfScore4, 
    VisitDate5, Task5, RfScore5, PfScore5, 
    VisitDate6, Task6, RfScore6, PfScore6 
from 
(
    select id, 
    col = col + cast(seq as varchar(10)), 
    value 
    from 
    (
    select id, task, [visit date], [rf score], [pf score], 
     row_number() over(partition by id 
         order by [visit date]) seq 
    from yourtable 
) d 
    cross apply 
    (
    values 
     ('VisitDate', convert(varchar(10), [visit date], 120)), 
     ('Task', [task]), 
     ('RfScore', cast([rf score] as varchar(10))), 
     ('PfScore', cast([pf score] as varchar(10))) 
) c (col, value) 
) d 
pivot 
(
    max(value) 
    for col in (VisitDate1, Task1, RfScore1, PfScore1, 
       VisitDate2, Task2, RfScore2, PfScore2, 
       VisitDate3, Task3, RfScore3, PfScore3, 
       VisitDate4, Task4, RfScore4, PfScore4, 
       VisitDate5, Task5, RfScore5, PfScore5, 
       VisitDate6, Task6, RfScore6, PfScore6) 
) piv; 

См SQL Fiddle with Demo.

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

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(col + cast(seq as varchar(10))) 
        from 
        (
         select row_number() over(partition by id 
               order by [visit date]) seq 
         from yourtable 
        ) d 
        cross apply 
        (
         select 'VisitDate', 1 union all 
         select 'Task', 2 union all 
         select 'RfScore', 3 union all 
         select 'PfScore', 4 
        ) c (col, so) 
        group by seq, col, so 
        order by seq, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'select id, ' + @cols + ' 
      from 
      (
       select id, 
       col = col + cast(seq as varchar(10)), 
       value 
       from 
       (
       select id, task, [visit date], [rf score], [pf score], 
        row_number() over(partition by id 
            order by [visit date]) seq 
       from yourtable 
      ) d 
       cross apply 
       (
       values 
        (''VisitDate'', convert(varchar(10), [visit date], 120)), 
        (''Task'', task), 
        (''RfScore'', cast([rf score] as varchar(10))), 
        (''PfScore'', cast([pf score] as varchar(10))) 
      ) c (col, value) 
      ) s 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

См SQL Fiddle with Demo.Обе версии дают результат:

| ID | VISITDATE1 |   TASK1 | RFSCORE1 | PFSCORE1 | VISITDATE2 |   TASK2 | RFSCORE2 | PFSCORE2 | VISITDATE3 |   TASK3 | RFSCORE3 | PFSCORE3 | VISITDATE4 |   TASK4 | RFSCORE4 | PFSCORE4 | VISITDATE5 |   TASK5 | RFSCORE5 | PFSCORE5 | VISITDATE6 |   TASK6 | RFSCORE6 | PFSCORE6 | VISITDATE7 |   TASK7 | RFSCORE7 | PFSCORE7 | VISITDATE8 |   TASK8 | RFSCORE8 | PFSCORE8 | 
|-------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------|------------|-----------------|----------|----------| 
| 5180 | 2011-06-09 | Initial Visit |  3 |  9 | 2011-07-08 | Follow Up Visit |  3 |  10 | 2011-09-02 | Follow Up Visit |  1 |  10 |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) | 
| 5199 | 2011-09-08 | Follow Up Visit |  5 |  6 | 2011-09-15 | Follow Up Visit |  2 |  7 | 2011-10-13 | Follow Up Visit |  4 |  8 | 2011-10-20 | Follow Up Visit |  2 |  4 | 2011-10-27 | Follow Up Visit |  4 |  7 | 2011-11-03 | Follow Up Visit |  3 |  3 | 2011-11-10 | Follow Up Visit |  2 |  5 | 2011-11-17 | Follow Up Visit |  3 |  4 | 
| 10219 | 2013-12-26 | Follow Up Visit |  1 |  6 |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) |  (null) |   (null) | (null) | (null) | 
Смежные вопросы