Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 将多行中的数据转换为单行(值不是标准值)_Sql_Sql Server 2008_Tsql_Pivot - Fatal编程技术网

Sql 将多行中的数据转换为单行(值不是标准值)

Sql 将多行中的数据转换为单行(值不是标准值),sql,sql-server-2008,tsql,pivot,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 |

我的问题是:

我有一张有姓名和地址的桌子

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
请注意,a的第一个条目“12车道”没有出现

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


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

你可以旋转它。关键点是按更新的降序为地址分配行号。这将生成列名称1、2和3(以及4、5-但这些将被pivot命令忽略)


下面是一个使用
ROW\u 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

可以考虑使用两个查询:

  • 第一种方法是使用DISTINCT键获取唯一的“名称”

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

  • 当然,可以使用合适的联接组合查询


到目前为止您都做了些什么?我一直在尝试将所有地址连接到一列中。。即将尝试将它们拆分为我需要填充的3个地址字段。谢谢约翰和尼古拉的快速回复!我要先试试尼古拉的方法,因为它看起来又短又甜。谢谢尼古拉,这本书写得很优美,效果很好!
;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