行を列に変換する最も効率的な方法を探しています。データベースの内容 (以下の実際のスキーマではありませんが、概念は似ています) を固定幅形式と区切り形式の両方で出力する必要があります。以下の 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
ピボットを見てきましたが、見つけた例のほとんどは情報を集約しています。子行を結合して親に追加したいだけです。
また、子行の出力は固定幅の文字列または区切り文字列のいずれかになるため、列名を処理する必要がないことも指摘しておく必要があります。
たとえば、次の表があるとします。
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 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
私が望むものを出力しますが、大量のデータの場合は非常に遅くなります。子テーブルの 1 つが 200 万行を超えているため、処理時間が最大 4 時間かかります。
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250