多行数据到单行(值不标准)

时间:2012-09-04 08:06:10

标签: sql sql-server-2008 tsql pivot

这是我的问题:

我有一个名称和地址表,例如

Name  |  Address       | Updated
----------------------------------
a     |  12 lane       | 1/1/2011
b     |  34 avenue     | 1/1/2011
c     |  56 district   | 1/1/2011
a     |  78 avenue     | 8/8/2011
b     |  90 lane       | 8/8/2011
a     |  83 district   | 9/9/2011
a     |  39 road       | 10/10/2011

如您所见,人们可能拥有多个地址。假设一个人拥有的最大地址数为5。

我只对每个人获得最新的3个地址感兴趣,这样表格看起来像:

Name  |  Address_1      |   Address_2       |  Address_3
--------------------------------------------------------------
a     | 78 avenue       |   83 district     | 39 road
b     | 34 avenue       |   90 lane         | NULL
c     | 56 district     |   NULL            | NULL

请注意,第一个条目“12 lane”不会出现

我一直在阅读stackoverflow上显示的其他示例,但我不确定Pivot表是否适合我需要的,因为地址都不同

提前感谢您提供的任何帮助!

3 个答案:

答案 0 :(得分:6)

你可以转动它。关键点是按更新的降序将row_numbers分配给地址。这会产生列名1,2和3(和4,5 - 但这些将被pivot命令忽略)。

Here is Sql Fiddle with example

select name, 
       [1] Address_1,
       [2] Address_2,
       [3] Address_3
from
(
  select name,
         address,
         row_number() over (partition by name
                            order by updated desc) rn
    from table1
) o
pivot (min(address) for rn in ([1], [2], [3])) p

答案 1 :(得分:1)

以下是使用ROW_NUMBER()

的简单查询

由于您只需要三个地址列,因此这可能是合适的。该解决方案不适用于非固定数量的色谱柱。

;with testdata(Name, Address, Updated)
as
(
select 'a','12 lane',convert(datetime, '1/1/2011')
union all
select 'b','34 avenue',convert(datetime, '1/1/2011')
union all
select 'c','56 district',convert(datetime, '1/1/2011')
union all
select 'a','78 avenue',convert(datetime, '8/8/2011')
union all
select 'b','90 lane',convert(datetime, '8/8/2011')
union all
select 'a','83 district',convert(datetime, '9/9/2011')
union all
select 'a','39 road',convert(datetime, '10/10/2011')
)
,tmp
as
(
select  * 
        ,row_number() over(PARTITION by Name order by Updated desc) as rn
from testdata
)
select  x.Name
        ,x.Address
        ,y.Address
        ,z.Address
from    tmp x
left join   tmp y
    on  x.Name = y.Name
    and y.rn = 2
left join   tmp z
    on  x.Name = z.Name
    and z.rn = 3
where x.rn = 1

答案 2 :(得分:0)

您可以考虑使用两个查询:

  • 第一个使用DISTINCT键获取唯一的“名称”。

  • 第二个是在唯一名称的循环中,使用TOP子句(在您的情况下为TOP 3)和“ORDER BY Updated DESC”规范为每个名称获取3个最新地址。 / p>

  • 当然,可以使用合适的JOIN组合查询。