需要帮助来改进以下查询(基于Cte的解决方案)

时间:2011-06-16 12:07:05

标签: sql sql-server sql-server-2005 tsql common-table-expression

考虑以下输入表

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

所需的输出

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

我已经将查询写成可以正常工作

;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

但从表现来看,它非常糟糕...... 我正在寻找一个更好的查询,可以加快进程(可能不是我的xquery方法,但其他方法只使用cTE而没有RBar / procedural / while循环/光标方法)

即使我的查询可以改进,我也很好。

N.B.~我无法在表格上添加任何索引。请将此点视为对环境的限制。无论我需要做什么,只能使用查询。

N.B.~可以有更多的国家而不仅限于5

请帮忙......

提前致谢

1 个答案:

答案 0 :(得分:0)

如果您有一个由.分隔的四部分字符串,则可以使用parsename。由于您有五个国家/地区,因此您可以使用常规子字符串获取第一个国家/地区,然后移除第一个国家/地区,将所有,替换为.并使用parsename替换

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)

如果你知道你有8个国家,你可以这样做。

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)

如果您不知道有多少国家/地区需要动态构建查询。 The Curse and Blessings of Dynamic SQL