SQL将行放入列中,也许是PIVOT

时间:2009-08-30 22:46:18

标签: sql-server

我有一个带有电子商务店面数据库的MS SQL Server。

这是我的一些表格:

Products:  
Id | Name | Price

ProductAttributeTypes: -Color, Size, Format  
Id | Name

ProductAttributes: --Red, Green, 12x20 cm, Mirrored  
Id | ProductAttributeTypeId | Name

Orders:  
Id | DateCreated

OrderItems:  
Id | OrderId | ProductId

OrderItemsToProductAttributes: --Relates an OrderItem to its product and selected attributes  
OrderItemId | ProductAttributeId | ProductAttributeTypeId | ProductId

我想从OrderItems表中选择,以查看已购买的商品。

要查看选择了哪种变体(ProductAtriibutes),我希望这些变量在结果集中为“动态”列。

因此结果集应如下所示:

OrderItemId | ProductId | ProductName | Color | Size | Format  
       1234         123   Mount. Bike   Red     2x20   Mirror

我不知道PIVOT是否适用?我没有使用任何聚合函数,所以我猜不是......

有没有可以帮助我的SQL Ninjas?

3 个答案:

答案 0 :(得分:1)

如果您使用的是sql2005或2008,则可以使用pivot命令。见here.

在下面的示例中,OrderAttributes集将如下所示:

 OrderItemId AttName AttValue
       -----  ------  -----
        100 Color   Red
        100 Size    Small
        101 Color   Blue
        101 Size    Small
        102 Color   Red
        102 Size    Small
        103 Color   Blue
        103 Size    Large

PIVOT之后的最终结果将是:

OrderItemId Size  Color
  -----    ------  -----
    100 Small   Red
    101 Small   Blue
    102 Small   Red
    103 Large   Blue

WITH OrderAttributes(OrderItemId, AttName, AttValue)
   AS (
      SELECT 
         OrderItemId, 
         pat.Name AS AttName,
         pa.Name AS AttValue
      FROM OrderItemsToProductAttributes x
      INNER JOIN ProductAttributes pa 
      ON x.ProductAttributeId = pa.id
      INNER JOIN ProductAttributeTypes pat
      ON pa.ProductAttributeTypeId =  pat.Id
   )

SELECT AttrPivot.OrderItemId,
[Size] AS [Size],
[Color] AS Color
FROM OrderAttributes
PIVOT ( 
      MAX([AttValue])
      FOR [AttName] IN ([Color],[Size])
   ) AS AttrPivot
ORDER BY AttrPivot.OrderItemId

有一种方法可以动态构建列(即颜色和大小列),可以看出here.确保数据库上的数据库兼容级别设置为大于2000的值,否则您将获得奇怪的错误。

答案 1 :(得分:0)

过去,我创建的物理表仅供阅读之用。您上面的结构对于存储而言非常好,但报告很糟糕。

所以你可以做以下事情: 编写一个脚本(每晚安排)或触发器(在数据更改时)执行以下任务:

首先,您将动态浏览每个产品并构建一个静态表“Product_ [ProductName]”

然后浏览每个产品的每个ProductAttributeTypes,并在相应的Product表上创建/更新/删除物理列。

然后,使用基于OrderItemsToProductAttributes和ProductAttributes的正确值填充该表

这只是一个粗略的想法。确保将OrderID存储在“静态”/“展平”表中。并确保你做了你需要做的一切。但在那之后,您应该能够从那些平坦的表中拉出来获取所需的数据。

答案 2 :(得分:0)

Pivot是你最好的选择,但我为报告目的而做的,并使其与SSIS配合良好是创建一个视图,然后有这个查询:

SELECT     [InputSetID], [InputSetName], CAST([470] AS int) AS [Created By], CAST([480] AS datetime) AS [Created], CAST([479] AS int) AS [Updated By], CAST([460] AS datetime) 
                      AS [Updated]
FROM         (SELECT     st.InputSetID, st.InputSetName, avt.InputSetID AS avtID, avt.AttributeID, avt.Value
                       FROM          app.InputSetAttributeValue avt JOIN
                                              app.InputSets st ON avt.InputSetID = st.InputSetID) AS p PIVOT (MAX(Value) FOR AttributeID IN ([470], [480], [479], [460])) AS pvt

然后我可以只与视图交互,但是,我在表上有一个触发器,必须添加任何新的动态属性,这会重新创建此视图,因此我可以假设视图始终是正确的。