2014-01-09 16 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 

與被結構類似這樣的數據沒有人知道如何將這些行轉換成列動態,即使我不知道需要多少列?

編輯:最後的結果應該是這樣的:

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

爲什麼你需要在SQL中執行這種類型的PIVOT?你能不能把結果返回給你的客戶,按照ID,Date排序,並保持水平直到你點擊一個新的ID? –

回答

2

solution that you link to將努力爲您的情況,但你有,因爲你想在轉動數據的多個列小幅調整。由於您需要對多個列進行透視,因此您首先需要將您的Visit Date,Task,Rf ScorePf Score列轉化爲多行,然後應用透視函數。除了不透明的過程之外,我還建議使用,如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 ScorePf Score中的每個值與實際訪問次數關聯起來。

一旦你有這個行號,那麼你會希望將你的多列轉化爲多行數據。有幾種方法可以做到這一點,包括使用unpivot功能。但因爲你正在使用SQL Server 2008 R2,您可以使用CROSS APPLYVALUES

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將非常具有:

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