1

我正在寻找将行转换为列的最高效方法。我需要以固定宽度和分隔格式输出数据库的内容(不是下面的实际模式,但概念相似)。下面的 FOR XML PATH 查询给出了我想要的结果,但是在处理除少量数据之外的任何内容时,可能需要一段时间。

 select orderid
   ,REPLACE((  SELECT '  ' + CAST(ProductId as varchar)
       FROM _details d
       WHERE d.OrderId = o.OrderId
       ORDER BY d.OrderId,d.DetailId
       FOR XML PATH('')
   ),' ','') as Products
 from _orders o

我已经查看了 pivot 但我发现的大多数示例都是聚合信息。我只想合并子行并将它们附加到父行上。

我还应该指出,我也不需要处理列名,因为子行的输出要么是固定宽度的字符串,要么是分隔的字符串。

例如,给定下表:

OrderId     CustomerId
----------- -----------
1           1
2           2
3           3

DetailId    OrderId     ProductId
----------- ----------- -----------
1           1           100
2           1           158
3           1           234
4           2           125
5           3           101
6           3           105
7           3           212
8           3           250

对于我需要输出的订单:

orderid     Products
----------- -----------------------
1             100  158  234
2             125
3             101  105  212  250

或者

orderid     Products
----------- -----------------------
1           100|158|234
2           125
3           101|105|212|250

想法或建议?我正在使用 SQL Server 2k5。

示例设置:

   create table _orders (
  OrderId int identity(1,1) primary key nonclustered
  ,CustomerId int
 )

 create table _details (
  DetailId int identity(1,1) primary key nonclustered
  ,OrderId int 
  ,ProductId int
 )

 insert into _orders (CustomerId)
 select 1
 union select 2
 union select 3

 insert into _details (OrderId,ProductId)
 select 1,100
 union select 1,158
 union select 1,234
 union select 2,125
 union select 3,105
 union select 3,101
 union select 3,212
 union select 3,250

 CREATE CLUSTERED INDEX IX_CL__orders on _orders(OrderId)
 CREATE NONCLUSTERED INDEX IX_NCL__orders on _orders(OrderId)
 INCLUDE (CustomerId)

 CREATE CLUSTERED INDEX IX_CL_details on _details(OrderId)
 CREATE NONCLUSTERED INDEX IX_NCL_details on _details(OrderId)
 INCLUDE (DetailId,ProductId)

使用 FOR XML 路径:

 select orderid
   ,REPLACE((  SELECT '  ' + CAST(ProductId as varchar)
       FROM _details d
       WHERE d.OrderId = o.OrderId
       ORDER BY d.OrderId,d.DetailId
       FOR XML PATH('')
   ),' ','') as Products
 from _orders o

它输出我想要的东西,但是对于大量数据来说非常慢。其中一个子表超过 200 万行,将处理时间推迟到 4 小时左右。

orderid     Products
----------- -----------------------
1             100  158  234
2             125
3             101  105  212  250
4

1 回答 1

1

根据定义,一个 PIVOT 将不得不以某种方式聚合,因为您可以有多个具有相同枢轴键列的行。如果您没有多行,那很好 - 但您仍然需要选择聚合运算符(MIN、MAX、SUM)。

但是FOR XML PATH对于多行值到单字符串列的“枢轴”操作,该构造更好。

我不确定为什么你的表现不好。你在表上有什么索引?你的执行计划是什么样的?

于 2010-04-12T21:13:58.413 回答