2014-01-05 306 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) |