2010-04-12 4 views
1

행을 열로 변환하는 가장 효과적인 방법을 찾고 있습니다. 나는 db의 내용을 출력해야한다는 요구 사항을 가지고있다. (실제 스키마는 아니지만 개념은 비슷하다.) 고정 너비와 구분 된 형식으로되어있다. 아래의 FOR XML PATH 쿼리를 사용하면 원하는 결과를 얻을 수 있지만 소량의 데이터를 처리하는 경우에는 잠시 시간이 걸릴 수 있습니다.t-sql에서 열로 가장 효율적인 행? x32 경로에 대한 크로스 탭, 피벗

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) 

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 

그러나 많은 양의 데이터를 매우 느립니다. 하위 테이블 중 하나가 2 백만 행을 초과하여 처리 시간이 ~ 4 시간으로 단축되었습니다.

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

답변

0

피벗은 동일한 피벗 키 열을 사용하여 여러 행을 가질 수 있으므로 어떤 방식 으로든 집계해야합니다. 여러 행이 없어도 괜찮습니다. 그러나 집계 연산자 (MIN, MAX, SUM)를 선택해야합니다.

그러나 FOR XML PATH 구조는 다중 행 값에서 단일 문자열 열 "피벗"작업에 더 좋습니다.

귀하의 실적이 좋지 않은 이유가 확실하지 않습니다. 테이블에 어떤 인덱스가 있습니까? 실행 계획은 어떻게 생겼습니까?

+0

기본 키 열에 클러스터 된 인덱스가 있고 기본 키 열에 비 클러스터형 인덱스가 있으며 테이블의 다른 모든 열에 포함됩니다. – ajberry

+0

@ajberry - 세부 정보 테이블에 OrderId, DetailId에 대한 키가 있습니까? ProductId가 포함되어 있습니까? –

+0

위의 예제 설정에서 테이블에있는 인덱스를 추가했습니다. 실제 테이블의 인덱스를 다시 확인해야합니다. 튜닝이있을 수 있습니다. – ajberry