2014-01-05 308 views
0

我在SQL 3列 - 姓名,編號和日期:樞軸列

Name CarID Period 
--------------------- 
Bob  121  Jan 08 
Bob  123  Jan 08 
Bob  121  Feb 08 
Steve 121  Jan 08 
Ruth 139  Feb 08 

我需要轉動的CarID旁邊獨特的名稱和週期,即:

Name Period Col1 Col2 Col3 
------------------------------------- 
Bob  Jan 08 121  123 NULL 
Bob  Feb 08 121  NULL NULL 
Steve Jan 08 121  NULL NULL 
Ruth Feb 08 139  NULL NULL 

我問題是,一個指定的用戶可能有1或x個CarID與他們的名字相反。我已經嘗試了一些動態數據透視查詢,但他們都必須設置列標題名稱。

+0

你正在尋找一個「交叉表」。見http://www.postgresql.org/docs/9.3/static/tablefunc.html – maybeWeCouldStealAVan

+0

看着這個,看起來你需要知道你需要多少列? –

+0

@bluefeet我的腦部故障 - 我看到一個不存在的Postgresql標籤。 – maybeWeCouldStealAVan

回答

1

有幾種方法,你可以得到你想要的結果,但爲了順利返回多個carid值爲每個nameperiod,我會用一個窗口函數像row_number()生成的每個分區的唯一序列name/period

您的查詢將使用類似的開始:

select name, carid, period, 
    'col'+ 
    cast(row_number() over(partition by name, period 
          order by carid) as varchar(10)) seq 
from yourtable; 

SQL Fiddle with Demo。這將給你下面的數據,然後你可以將PIVOT轉換爲列。

| NAME | CARID | PERIOD | SEQ | 
|-------|-------|--------|------| 
| Bob | 121 | Feb 08 | col1 | 
| Bob | 121 | Jan 08 | col1 | 
| Bob | 123 | Jan 08 | col2 | 
| Ruth | 139 | Feb 08 | col1 | 
| Steve | 121 | Jan 08 | col1 | 

然後,您可以將此數據轉換成列,使用聚合功能,類似於一個CASE表達式:

select 
    name, 
    period, 
    max(case when seq = 'col1' then carid end) col1, 
    max(case when seq = 'col2' then carid end) col2, 
    max(case when seq = 'col3' then carid end) col3 
from 
(
    select name, carid, period, 
    'col'+ 
     cast(row_number() over(partition by name, period 
           order by carid) as varchar(10)) seq 
    from yourtable 
) d 
group by name, period; 

SQL Fiddle with Demo。這也可以轉換成使用PIVOT功能列:

select name, period, col1, col2, col3 
from 
(
    select name, carid, period, 
    'col'+ 
     cast(row_number() over(partition by name, period 
           order by carid) as varchar(10)) seq 
    from yourtable 
) d 
pivot 
(
    max(carid) 
    for seq in (col1, col2, col3) 
) p; 

參見SQL Fiddle with Demo。以上兩個疑問會是不錯的,如果你有值的數量有限,但如果你有未知的值,那麼你將不得不使用動態SQL生成結果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(seq) 
        from 
        (
         select 'col'+ 
          cast(row_number() over(partition by name, period 
                order by carid) as varchar(10)) seq 
         from yourtable 
        ) d 
        group by seq 
        order by seq 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT name, period,' + @cols + ' 
      from 
      (
       select name, carid, period, 
       ''col''+ 
        cast(row_number() over(partition by name, period 
              order by carid) as varchar(10)) seq 
       from yourtable 
      ) x 
      pivot 
      (
       max(carid) 
       for seq in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo。所有版本會給你類似的結果:

| NAME | PERIOD | COL1 | COL2 | 
|-------|--------|------|--------| 
| Bob | Feb 08 | 121 | (null) | 
| Ruth | Feb 08 | 139 | (null) | 
| Bob | Jan 08 | 121 | 123 | 
| Steve | Jan 08 | 121 | (null) |