2015-04-02 76 views
2

在SQL-Server的工作方法,我有如下表:如何做到這一點透視(轉)

visit temperature treatment denom num pct 
    A  <38°C   1   101  98  97.0 
    A  38.0-38.4°C 1   103  2  1.9 
    A  38.5-38.9°C 1   100  1  1.0 
    A  <38°C   2   100  97  97.0 
    A  38.0-38.4°C 2   100  1  1.0 
    A  38.5-38.9°C 2   102  4  3.9 
    B  <38°C   1   101  89  88.1 
    B  38.0-38.4°C 1   100  2  2.0 
    B  38.5-38.9°C 1   105  1  1.0 
    B  <38°C   2   104  96  96.4 
    B  38.0-38.4°C 2   104  5  1.8 
    B  38.5-38.9°C 2   100  3  3.0 

應該怎樣做,以使表看起來像這樣?:

visit temperature name   _1  _2 
    A  <38°C   denom  101.0 100.0 
    A  <38°C   num   98.0  97.0 
    A  <38°C   pct   97.0  97.0 
    A  38.0-38.4°C denom  103.0 100.0 
    A  38.0-38.4°C num   2.0  1.0 
    A  38.0-38.4°C pct   1.9  1.0 
    A  38.5-38.9°C denom  100.0 102.0 
    A  38.5-38.9°C num   1.0  4.0 
    A  38.5-38.9°C pct   1.0  3.9 
    B  <38°C   denom  101.0 104.0 
    B  <38°C   num   89.0  96.0 
    B  <38°C   pct   88.1  96.4 
    B  38.0-38.4°C denom  100.0 104.0 
    B  38.0-38.4°C num   2.0  5.0 
    B  38.0-38.4°C pct   2.0  1.8 
    B  38.5-38.9°C denom  105.0 100.0 
    B  38.5-38.9°C num   1.0  3.0 
    B  38.5-38.9°C pct   1.0  3.0 

其中數字列中的_n是治療發生的次數,對於某些訪問可能有500次治療,如何有效處理這些數據,而無需將_1指定爲第一個旋轉列,_2作爲第二個旋轉列,...,_n作爲最後一個樞軸列?

感謝

+1

你真的想在輸出500列?這是否會有意義,即人們是否真的要閱讀所有500列?通過有效地引用查詢的性能,或者不必寫出列,例如'(1),[2],[3],... [n])的PIVOT(最大(價值)治療)如果只有3種治療方案,那麼應該只有3列? – GarethD 2015-04-02 16:35:27

回答

6

爲了得到你想要的結果,你將不得不UNPIVOT你denomnumpct列,然後轉動的treatments。要UNPIVOT,你可以使用CROSS APPLY甚至UNPIVOT列 - 這與多個列轉換爲多行:

select t.visit, t.temperature, t.treatment, 
    name, 
    val 
from yourtable t 
cross apply 
(
    select 'denom', denom union all 
    select 'num', num union all 
    select 'pct', pct 
) c (name, val) 

Demo。然後應用PIVOT:

select visit, temperature, name, [1], [2] 
from 
(
    select t.visit, t.temperature, t.treatment, 
    name, 
    val 
    from yourtable t 
    cross apply 
    (
    select 'denom', denom union all 
    select 'num', num union all 
    select 'pct', pct 
) c (name, val) 
) d 
pivot 
(
    max(val) 
    for treatment in ([1], [2]) 
)piv; 

請參閱SQL Fiddle with Demo。現在上面的代碼會要求你寫出你所有的treatment,如果你有一個未知的數字,那麼你需要使用動態SQL。動態SQL創建一個字符串,然後執行:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(treatment) 
        from yourtable 
        group by treatment 
        order by treatment 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT visit, temperature, name,' + @cols + ' 
      from 
      (
       select t.visit, t.temperature, t.treatment, 
        name, 
        val 
       from yourtable t 
       cross apply 
       (
        select ''denom'', denom union all 
        select ''num'', num union all 
        select ''pct'', pct 
       ) c (name, val) 
      ) x 
      pivot 
      (
       max(val) 
       for treatment in (' + @cols + ') 
      ) p ' 

exec sp_executesql @query; 

SQL Fiddle with Demo。這些都給:

| visit | temperature | name | 1 | 2 | 
|-------|-------------|-------|------|------| 
|  A |  <38°C | denom | 101 | 100 | 
|  A |  <38°C | num | 98 | 97 | 
|  A |  <38°C | pct | 97 | 97 | 
|  A | 38.0-38.4°C | denom | 103 | 100 | 
|  A | 38.0-38.4°C | num | 2 | 1 | 
|  A | 38.0-38.4°C | pct | 1.9 | 1 | 
|  A | 38.5-38.9°C | denom | 100 | 102 | 
|  A | 38.5-38.9°C | num | 1 | 4 | 
|  A | 38.5-38.9°C | pct | 1 | 3.9 | 
|  B |  <38°C | denom | 101 | 104 | 
|  B |  <38°C | num | 89 | 96 | 
|  B |  <38°C | pct | 88.1 | 96.4 | 
|  B | 38.0-38.4°C | denom | 100 | 104 | 
|  B | 38.0-38.4°C | num | 2 | 5 | 
|  B | 38.0-38.4°C | pct | 2 | 1.8 | 
|  B | 38.5-38.9°C | denom | 105 | 100 | 
|  B | 38.5-38.9°C | num | 1 | 3 | 
|  B | 38.5-38.9°C | pct | 1 | 3 | 
+0

Didn' t知道你可以使用CROSS APPLY到UNPIVOT ...顯然它工作正如我從SQL小提琴中看到的那樣。是否有任何理由不使用UNPIVOT?使用CROSS APPLY而不是UNPIVOT有什麼好處? – 2015-04-02 20:29:48

+1

@TT。在這一點上,使用CROSS APPLY只是一種習慣,因爲當你必須成對取消轉換列時,它會更容易轉換爲unpivot。另外如果你有不同的數據類型,你可以很容易地在CROSS APPLY中轉換/轉換它們,而不必使用子查詢,但你可以看到UNPIVOT的工作原理相同--http://sqlfiddle.com/#!6/6c614/9 – Taryn 2015-04-02 20:32:57

+0

好東西,很高興知道 – 2015-04-02 20:36:42