0

Tenir compte de la table d'entrée ci-dessousBesoin d'aide pour améliorer la requête ci-dessous (solution Cte)

Id CountryName 
1 India,Australia,Singapore,Pakistan,Bangaladesh 
2 Norway,Argentina,Brazil,WestIndies,Burma 

sortie souhaité être

Id Country1 Country2 Country3 Country4 Country5 
1 India Australia Singapore Pakistan Bangalades 
2 Norway Argentina Brazil WestIndies Burma 

Je writen la requête en vertu de laquelle fonctionne bien

;WITH cte AS (

SELECT 
Id, 
CAST('<i>' + REPLACE(CountryName, ',', '</i><i>') + '</i>' AS XML) AS names 
FROM @t 
) 

SELECT * FROM 
(
SELECT 
Id, 
x.i.value('.', 'VARCHAR(10)') AS Country, 
'Country' + CAST(s.Number AS VARCHAR) AS CountryType 
FROM cte 
CROSS APPLY master..spt_values s 
CROSS APPLY names.nodes('//i[position()=sql:column("s.number")]') x(i) 
WHERE s.type='p' 
) a 
PIVOT (
MAX(Country) FOR CountryType IN (Country1, Country2, Country3, Country4,Country5) 
) pvt 

Mais par la performance c'est très mauvais ... Je cherche une meilleure requête qui peut accélérer le processus (qui peut ne pas être l'approche xquery de ma mais l'autre approche en utilisant cTE seulement et aucune approche RBar/procedural/while loop/cursor)

Même si je suis d'accord si ma requête peut être améliorée. NB: Je ne peux pas ajouter d'indexation sur la table. Veuillez considérer ce point comme une limitation de l'environnement. Tout ce que j'ai à faire est avec la requête seulement.

NB ~ Il peut y avoir plus de pays et ne se limite pas à 5

S'il vous plaît aider ....

Merci à l'avance

Répondre

0

Vous pouvez utiliser parsename si vous avez une chaîne à quatre parties séparées par .. Puisque vous avez cinq pays, vous pouvez obtenir le premier avec une sous-chaîne régulière, puis retirer le premier pays, remplacer tous , avec . et utiliser parsename pour le reste

declare @T table(Id int, CountryName varchar(50)) 
insert into @T values 
(1, 'India,Australia,Singapore,Pakistan,Bangaladesh'), 
(2, 'Norway,Argentina,Brazil,WestIndies,Burma') 

select Id, 
    substring(CountryName, 1, charindex(',', CountryName)-1) as Country1, 
    parsename(T.N, 4) as Country2, 
    parsename(T.N, 3) as Country3, 
    parsename(T.N, 2) as Country4, 
    parsename(T.N, 1) as Country5 
from @T 
    cross apply(select replace(stuff(CountryName, 1, charindex(',', CountryName), ''), ',', '.')) as T(N) 

Si vous savez que vous avez 8 pays que vous pouvez faire ce.

declare @T table(Id int, CountryName varchar(100)) 
insert into @T values 
(1, 'India,Australia,Singapore,Pakistan,Bangaladesh,Denmark,Germany,France'), 
(2, 'Norway,Argentina,Brazil,WestIndies,Burma,South Africa,Spain,Portugal') 


select Id, 
    parsename(T1.N, 4) as Country1, 
    parsename(T1.N, 3) as Country2, 
    parsename(T1.N, 2) as Country3, 
    parsename(T1.N, 1) as Country4, 
    parsename(T2.N, 4) as Country5, 
    parsename(T2.N, 3) as Country6, 
    parsename(T2.N, 2) as Country7, 
    parsename(T2.N, 1) as Country8 
from @T 
    cross apply(select charindex(',', CountryName, charindex(',', CountryName, charindex(',', CountryName, charindex(',', CountryName)+1)+1)+1)) as S(P) 
    cross apply(select replace(substring(CountryName, 1, S.P-1), ',', '.')) as T1(N) 
    cross apply(select replace(stuff(CountryName, 1, S.P, ''), ',', '.')) as T2(N) 

Si vous ne savez pas combien de pays vous avez, vous devez créer la requête dynamiquement. The Curse and Blessings of Dynamic SQL

Questions connexes