规范化查询中的一行数据 - 将一行变为多行

时间:2017-11-16 22:16:53

标签: sql sql-server-2012

有没有更好的方法,我正在使用SQL Server 2012.

我有一个由供应商构建的表,如下所示:

Customer, Date, Desc1, Qty1, Price1, Desc2, Qty2, Price2, Desc3, Qty3, Price3

我想要一个返回此结果的结果集;

Customer, Date, Desc, Qty, Price  

我今天通过以下解决方案来做,任何人都有更好或更高效的东西?

Select Customer, Date, Desc1, Qty1, Price1
UNION ALL
Select Customer, Date, Desc2, Qty2, Price2
UNION ALL
Select Customer, Date, Desc3, Qty3, Price3

2 个答案:

答案 0 :(得分:2)

这是SQL Server的替代方案;它使用cross applyvalues,它是unpivot命令的有效且非常灵活的替代品,对于"规范化"非常有用。数据

select Customer, Date, ca.description, ca.qty, ca.price
from YourTable
cross apply (
   values
      (Desc1, Qty1, Price1)
    , (Desc2, Qty2, Price2)
    , (Desc3, Qty3, Price3)
    , (Desc4, Qty4, Price4)
    ) ca (description, qty, price)

NB values区域中的每一行都会形成一个新的输出行,因此,如上所示布局时,它在视觉上与最终布局相似。

有关详细信息,请参阅:Spotlight on UNPIVOT, Part 1(Brad Schultz)

答案 1 :(得分:1)

UNION ALL方法运行正常。但是,CROSS APPLY

可能具有不同的性能或可读性
SELECT t1.Customer,
    t1.[Date],
    x.[Desc],
    x.Qty,
    x.Price
FROM UnnamedTable t1
CROSS APPLY (
    VALUES (Desc1, Qty1, Price1),
        (Desc2, Qty2, Price2),
        (Desc3, Qty3, Price3)
    ) x ([Desc], Qty, Price);

假设每个重复组实际上是相同的数据类型。也就是说,Qty1Qty2Qty3都是int(或类似),依此类推。

或者,您可以使用UNPIVOT表达式,但老实说,我发现UNPIVOT的语法非常神秘。