【问题标题】:Convert tables with "id,attribute,value" columns to "id,attribute1,attribute2,..."将具有“id,attribute,value”列的表转换为“id,attribute1,attribute2,...”
【发布时间】:2011-04-29 22:58:22
【问题描述】:

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

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

为了利用一些数据,我需要让它看起来……像这样:

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

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

【问题讨论】:

    标签: sql-server tsql pivot


    【解决方案1】:

    如果这是 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
    

    【讨论】:

    • 非常感谢!这是我做梦也想不到的答案!
    【解决方案2】:

    听起来你需要 PIVOT。您应该阅读以下文章以了解如何做到这一点:

    PIVOT functionality in SQL Server

    【讨论】:

      【解决方案3】:

      鉴于以下情况:

      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 带来了所有至少具有一个属性的客户。

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

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

      源表名为vertical的表是具有属性值的表

      目标表命名为横向是您想要的输出

      【讨论】:

      • 谢谢,自我加入一直是一种选择,但我个人不喜欢它,因为它很难看。 Pivot 似乎是一个更好的解决方案。
      猜你喜欢
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多