SQL - 为每个列创建一行并重复ID

时间:2016-10-28 19:27:00

标签: mysql sql tsql

我希望能够可视化快照数据并限制我需要创建的列数。我的数据看起来像这样。

+----+-------+---------+--------+-------+
| ID |   A   |    B    |   C    |   D   |
+----+-------+---------+--------+-------+
|  1 | Adam  | Anthony | Andy   | Alice |
|  2 | Bob   | Brain   | Bill   | Bing  |
|  3 | Cindy | Cal     | Chris  | Cathy |
|  4 | Dave  | DJ      | Dillon | Dan   |
+----+-------+---------+--------+-------+

我希望它看起来像这样

+----+--------+---------+
| ID | Column |  Value  |
+----+--------+---------+
|  1 | A      | Adam    |
|  1 | B      | Anthony |
|  1 | C      | Andy    |
|  1 | D      | Alice   |
|  2 | A      | Bob     |
|  2 | B      | Brain   |
|  2 | C      | Bill    |
|  2 | D      | Bing    |
|  3 | A      | Cindy   |
|  3 | B      | Cal     |
|  3 | C      | Chris   |
|  3 | D      | Cathy   |
|  4 | A      | Dave    |
|  4 | B      | DJ      |
|  4 | C      | Dillon  |
|  4 | D      | Dan     |
+----+--------+---------+

3 个答案:

答案 0 :(得分:1)

您可以使用UNION查询执行此操作:

SELECT id, 'A', A as Value FROM table
UNION ALL
SELECT id, 'B', B FROM table
UNION ALL 
SELECT id, 'C', C FROM table
UNION ALL 
SELECT id, 'D', D FROM table;

答案 1 :(得分:0)

如果真的是SQL Server,我经常使用帮助器Table-Valued-Function将行或查询转换为EAV结构(Entity Attribute Value)。无需指定所有需要的字段。

性能很好,但对于较大的数据集 UNPIVOT远优于

请考虑以下事项:

Declare @User table (ID int,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50))
Insert into @User values
(1,'John','Smith','john.smith@email.com'),
(2,'Jane','Doe'  ,'jane.doe@email.com')

Select B.*
 From  @User A
 Cross Apply [dbo].[udf-EAV]((Select A.* for XML RAW)) B

返回

enter image description here

在上面的示例中,该函数用于CROSS APPLY。它也可以用作独立呼叫

Select * from [dbo].[udf-EAV]((Select * from @User for XML RAW))

该职能感兴趣

CREATE FUNCTION [dbo].[udf-EAV](@XML xml)
Returns Table 
As
Return (
    with cteKey(k) as (Select Top 1 xAtt.value('local-name(.)','varchar(100)') From @XML.nodes('/row') As A(xRow) Cross Apply A.xRow.nodes('./@*') As B(xAtt))    

    Select Entity    = xRow.value('@*[1]','varchar(50)')
          ,Attribute = xAtt.value('local-name(.)','varchar(100)')
          ,Value     = xAtt.value('.','varchar(max)') 
    From  @XML.nodes('/row') As A(xRow)
    Cross Apply A.xRow.nodes('./@*') As B(xAtt)
    Where xAtt.value('local-name(.)','varchar(100)') Not In (Select k From cteKey)
)
-- Notes:  First Field in Query will be the Entity
-- Select * From [dbo].[udf-EAV]((Select UTCDate=GetUTCDate(),* From sys.dm_os_sys_info for XML RAW))

答案 2 :(得分:0)

如果您使用SQL Server,则可以尝试使用pivot / unpivot

由于您尝试将列(A,B,C,D)旋转到行,因此可以按如下方式使用unpivot:

 SELECT ID, [Column], [Value]
 FROM 
     (SELECT ID, A, B, C, D
     FROM InitialTable) p
 UNPIVOT
 (Value FOR Column IN 
   (A, B, C, D)
 )AS unpvt;
 GO