SQL提取以特定字符开头的字符串

时间:2019-04-05 02:16:11

标签: sql sql-server sql-server-2008

我有一列,其中包含用空格和逗号分隔的字符串。看起来像:

Column1
----------------------------
T1234, C1234, D1234, C1234
E1234, C1234

我需要一个SQL查询来提取以C开头的所有内容。因此结果如下:

Column1
--------------
C1234, C1234
C1234

2 个答案:

答案 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 <>小提琴。