将具有“id,attribute,value”列的表转换为“id,attribute1,attribute2,...”

时间:2010-10-24 21:13:50

标签: sql-server tsql pivot

我在数据库中有一个如下所示的表:

CustomerId    Attribute    Value
================================
30            Name         John
30            Surname      Smith
30            Phone        555123456

使用我需要的数据来使它看起来......像这样:

CustomerId    Name    Surname    Phone
======================================
30            John    Smith      555123456

我知道我可以为我创建存储过程或表值函数,但我想知道这里最好的选择是什么?也许我只能通过一些聪明的sql select查询来做到这一点?

3 个答案:

答案 0 :(得分:4)

如果这是SQL Server 2005或更高版本,则可以使用PIVOT

with Customers (CustomerId, Attribute, Value)
as
(
    select 30, 'Name', 'John'
    union
    select 30, 'Surname', 'Smith'
    union
    select 30, 'Phone', '551123456'
    union
    select 40, 'Name', 'Mary'
    union
    select 40, 'Surname', 'Johnson'
    union
    select 40, 'Phone', '9991111234'
)
select CustomerId, Name, Surname, Phone
from Customers
pivot
(
    min(Value)
    for Attribute in (Name, Surname, Phone)
) as PivotTable

或者不使用PIVOT的解决方案:

/* with cte defined as above */
select CustomerId, 
    max(case Attribute when 'Name' then Value else '' end) Name,
    max(case Attribute when 'Surname' then Value else '' end) Surname,
    max(case Attribute when 'Phone' then Value else '' end) Phone
from Customers
group by CustomerId

答案 1 :(得分:1)

听起来你需要PIVOT。您应该阅读以下文章以了解如何执行此操作:

PIVOT functionality in SQL Server

答案 2 :(得分:1)

鉴于以下情况:

create table vertical(
CustomerID int, 
attribute varchar(255),
value varchar(255)
)

create table horizontal(
CustomerID int, 
name varchar(255),
surname varchar(255),
phone varchar(255)
)

insert into vertical
    select 30, 'Name', 'John'
insert into vertical
    select 30, 'Surname', 'Smith'
insert into vertical
    select 30, 'Phone', '551123456'
insert into vertical
    select 40, 'Name', 'Mary'
insert into vertical
    select 40, 'Surname', 'Johnson'
insert into vertical
    select 40, 'Phone', '9991111234'
insert into vertical
    select 50, 'Surname', 'Manuel'
insert into vertical
    select 50, 'Phone', '423'

运行此插入

insert into horizontal (CustomerID, name, surname, phone)
select c.CustomerID, n.value as name, s.value as surname, ph.value as phone 
from 
 (select distinct CustomerID from vertical) as c
left join vertical n
    on c.CustomerID = n.CustomerID and n.attribute = 'name'
left join vertical s
    on c.CustomerID = s.CustomerID and s.attribute = 'Surname'
left join vertical ph
    on c.CustomerID = ph.CustomerID and ph.attribute = 'Phone'

应输出:

ID  Name    Surname Phone
--  ----    ------- -----
30  John    Smith   551123456
40  Mary    Johnson 9991111234
50  NULL    Manuel  423

其中:

来自: select distinct CustomerID from vertical为所有拥有至少一个属性的客户提供服务。

每个左连接返回每个属性的相应值。

左连接用于确保即使客户缺少某些属性也会插入客户行,在这种情况下会插入NULL。

名为vertical的

源表是具有属性值

的那个 名为horizo​​ntal的

目标表是您想要的输出