Sql server SQL将行转换为列,可能是PIVOT

Sql server SQL将行转换为列,可能是PIVOT,sql-server,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 O

我有一个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表中进行选择,以查看购买了哪些项目

要查看选择了哪种变体(ProductAttribute),我希望在resultset中将它们作为“动态”列

因此,结果集应该如下所示:

OrderItemId | ProductId | ProductName | Color | Size | Format  
       1234         123   Mount. Bike   Red     2x20   Mirror
我不知道PIVOT是否适合使用?我没有使用任何聚合函数,所以我想没有


有什么SQL忍者可以帮我吗?

过去,我创建物理表只是为了读取。上面的结构非常适合存储,但不适合报告

因此,您可以执行以下操作: 编写执行以下任务的脚本(每晚安排)或触发器(数据更改时):

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

然后检查每个产品的每个ProductAttributeType,并在相应的产品表上创建/更新/删除一个物理列

然后,根据OrderItemStopProductAttributes和ProductAttributes使用适当的值填充该表


这只是一个粗略的想法。确保在“静态”/“展平”表中存储OrderID。确保你做了所有你需要做的事情。但是在这之后,您应该能够开始从这些展开的表中提取所需的数据。

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

在下面的示例中,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
枢轴之后的最终结果将是:

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

有一种方法可以动态构建列(即颜色和大小列),如图所示,请确保数据库上的数据库兼容性级别设置为大于2000,否则会出现奇怪的错误。

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

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

我明白你的意思。我同意针对存储和报告的数据库设计有其冲突和局限性。但我认为这个查询不够重,无法使用聚合表,因为它会给我带来其他问题,如冗余、更新延迟等。如何解决?当我不使用任何聚合函数时?我不想对ID或诸如此类的内容进行汇总。我认为这一项现在非常接近——但是颜色和大小列的值都是空的。可能只是缺少一个小细节?有一件事可能会导致差异,您在OrderItemStopProductAttributes表中有ProductAttributeTypeId,我没有将其放在我的示例b/c中,这应该通过连接引用(第三个正常形式和全部)。如果您说它们可能有空值,那么应该将某些内容更改为:选择AttrPivot.OrderItemId,将isnull([Size],'NA')作为[Size],将isnull([Color],'NA')作为OrderAttributes中的颜色它没有空值。但我不知道为什么它返回null。如果在WITH语句中运行查询,则返回所有正确的数据-没有空值。但是,运行整个查询时,大小和颜色列的值都为空,我成功了。原因是每个属性的名称不存储为颜色、大小等。它存储为一个XML字符串,带有许多特定于区域性的值,以适应国际化。