t-sql più efficiente riga colonna? incrociato per XML Path, snodo
-
26-09-2019 - |
Domanda
Sto cercando il modo più performante per trasformare righe in colonne. Ho un requisito uscita il contenuto del db (non effettivo schema seguente, ma il concetto è simile) sia in larghezza fissa e formati delimitati. Il sotto query FOR XML PATH mi dà il risultato che voglio, ma quando si tratta di qualcosa di diverso da piccole quantità di dati, può prendere un po '.
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
Ho guardato perno ma la maggior parte degli esempi che ho trovato sono aggregazione delle informazioni. Voglio solo combinare le righe figlio e li virare sul genitore.
Vorrei anche sottolineare Non ho bisogno di trattare con i nomi delle colonne sia poiché l'uscita delle righe figlio o sarà una larghezza fissa stringa o una stringa delimitata.
Per esempio, date le seguenti tabelle:
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
per un ordine che ho bisogno di uscita:
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
o
orderid Products
----------- -----------------------
1 100|158|234
2 125
3 101|105|212|250
I pensieri o suggerimenti? Sto usando SQL Server 2k5.
Impostazione Esempio:
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)
utilizzando 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
che emette quello che voglio, ma è molto lento per grandi quantità di dati. Una delle tabelle figlio è oltre 2 milioni di righe, spingendo il tempo di elaborazione fuori a ~ 4 ore.
orderid Products
----------- -----------------------
1 100 158 234
2 125
3 101 105 212 250
Soluzione
Per definizione un perno sta per avere di aggregare in qualche modo, perché si può avere più righe con le stesse colonne chiave pivot. Se non si dispone di più righe, va bene -. Ma è ancora necessario scegliere un operatore di aggregazione (MIN, MAX, SUM)
Ma il costrutto FOR XML PATH
è migliore per i più righe valori per singola stringa-colonna "pivot" operazione.
Non sono sicuro perché vostro è non un buon rendimento. Che indici avete sui tavoli? Che cosa significa il vostro look piano di esecuzione come?