我有一列,其中包含用空格和逗号分隔的字符串。看起来像:
Column1
----------------------------
T1234, C1234, D1234, C1234
E1234, C1234
我需要一个SQL查询来提取以C开头的所有内容。因此结果如下:
Column1
--------------
C1234, C1234
C1234
答案 0 :(得分:1)
(mean ± std. dev. of 7 runs, 10 loops each)
返回:
declare @t table (c varchar(200) PRIMARY KEY)
insert into @t values ('T1234, C1234, D1234, C1234'), ('E1234, C1234')
;with cte1 as ( -- cte1 - number the rows. Order by PK
select row_number() over(order by c) rn, *
from @t
), cte2 as ( -- cte2 - turn comma delimited lists into rows of trimmed values
select rn, replace(ca.value, ' ', '') val
from cte1
cross apply (
select value from string_split((select c from cte1 cte1_inner where cte1_inner.rn = cte1.rn), N',')
)ca
), cte3 as ( -- cte3 - get distinct row numbers and re-concat vals in a subquery
select distinct rn, (
SELECT STUFF(
(
select ', ' + val
from cte2 cte2_inner
where val like 'c%' and cte2_inner.rn = cte2.rn
for xml path('')
), 1, 2, '')
)concatenated
from cte2
)
select concatenated
from cte3
这是每个CTE返回的内容:
cte1:
concatenated
C1234
C1234, C1234
cte2:
rn c
1 E1234, C1234
2 T1234, C1234, D1234, C1234
cte3:
rn val
1 E1234
1 C1234
2 T1234
2 C1234
2 D1234
2 C1234
答案 1 :(得分:1)
这也是使用递归CTE的机会:
with t as (
select 'T1234, C1234, D1234, C1234' as col1 union all
select 'E1234, C1234'
),
cte as (
select col1,
convert(varchar(max), (case when col1 like 'C%' then ', ' + left(col1, charindex(',', col1 + ',') - 1 ) else '' end)) as c_list,
convert(varchar(max), stuff(col1, 1, charindex(',', col1 + ',') + 1, '')) as rest,
1 as lev
from t
union all
select col1,
c_list + (case when rest like 'C%' then ', ' + left(rest, charindex(',', rest + ',') - 1 ) else '' end) ,
convert(varchar(max), stuff(rest, 1, charindex(',', rest + ',') + 1, '')) as rest,
lev + 1
from cte
where rest > '' and lev < 10
)
select stuff(c_list, 1, 2, '') as c_list
from (select cte.*, row_number() over (partition by col1 order by lev desc) as seqnum
from cte
) cte
where seqnum = 1;
此方法不需要提取字符串然后重新聚合。它还可以确保这些值保持原始数据中的原始顺序。
Here是db <>小提琴。