t-sql ligne la plus efficace à la colonne? croisé pour le chemin XML, pivot
-
26-09-2019 - |
Question
Je cherche le moyen le plus performant pour transformer les lignes en colonnes. J'ai une obligation de sortir le contenu de la DB (schéma ci-dessous non réel, mais le concept est similaire) en largeur fixe et formats délimités. La requête ci-dessous pour PATH XML me donne le résultat que je veux, mais quand traiter autre chose que de petites quantités de données, peut prendre un certain temps.
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
J'ai regardé pivot mais la plupart des exemples que j'ai trouvé regroupent des informations. Je veux juste combiner les lignes enfants et les virer de bord sur le parent.
Je tiens également à souligner que je ne ai pas besoin de traiter les noms de colonnes, soit depuis la sortie des lignes enfants seront soit une largeur fixe corde ou une chaîne Délimité.
Par exemple, étant donné les tableaux suivants:
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
pour un ordre que je dois sortie:
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
ou
orderid Products
----------- -----------------------
1 100|158|234
2 125
3 101|105|212|250
Pensées ou suggestions? J'utilise SQL Server 2k5.
Exemple de configuration:
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)
à l'aide du PATH 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
qui délivre ce que je veux, est cependant très lent pour de grandes quantités de données. L'une des tables de l'enfant est plus de 2 millions de lignes, poussant le temps de traitement vers ~ 4 heures.
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
La solution
Par définition, un PIVOT va devoir rassembler en quelque sorte, parce que vous pouvez avoir plusieurs lignes avec les mêmes colonnes de clés de pivot. Si vous n'avez pas plusieurs lignes, c'est très bien -. Mais vous devez toujours choisir un opérateur global (MIN, MAX, SUM)
Mais la construction de FOR XML PATH
est meilleur pour les lignes multiples valeurs à une seule chaîne colonne opération « pivot ».
Je ne sais pas pourquoi le vôtre ne fonctionne pas bien. Quels index avez-vous sur les tables? Qu'est-ce que votre look plan d'exécution comme?