我有以下字符串
KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52 IYT_2012_CBBI1_S_66_2012-09-21_15_28_53
例如:
2012_CBBE2_E_12704 2012_CBBI1_S_66
解决方法
方法1.嵌套的CHARINDEX调用.
使用CHARINDEX(‘_’,stringvalue)获取stringvalue中第一个_的位置.如果您将该位置作为第三个参数传递,则可以指示CHARINDEX从某个位置开始搜索:
CHARINDEX(`_`,stringvalue,startpos)
现在,如果起始位置是CHARINDEX(‘_’,stringvalue)1的结果,即如下:
CHARINDEX(`_`,CHARINDEX(`_`,stringvalue) + 1)
然后那会给你第二个_的位置.所以,要找到第五个_,你需要再多次嵌套CHARINDEX:
WITH aTable AS ( SELECT * FROM (VALUES ('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52'),('IYT_2012_CBBI1_S_66_2012-09-21_15_28_53') ) AS v (aStringColumn) ),positions AS ( SELECT aStringColumn,Underscore1 = CHARINDEX('_',aStringColumn),Underscore5 = CHARINDEX('_',aStringColumn,CHARINDEX('_',aStringColumn ) + 1 ) + 1 ) + 1 ) + 1 ) FROM aTable ) SELECT aSubstring = SUBSTRING(aStringColumn,Underscore1 + 1,Underscore5 - Underscore1 - 1 ) FROM positions ;
方法2.字符拆分排名.
>使用numbers table将每个字符串拆分为单个字符,沿途拉出它们的位置.
>对字符串中每个字符的出现进行排名.
>获取两个子集:
1)用字符_和排名1;
2)用字符_和排名5.
相互加入这些子集.
>与方法1类似,使用_#1和_#5的相应位置来获取子串.
WITH aTable AS ( SELECT * FROM (VALUES ('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52'),split AS ( SELECT t.aStringColumn,aChar = SUBSTRING(t.aStringColumn,n.Number,1),Position = n.Number FROM aTable t INNER JOIN Numbers n ON n.Number BETWEEN 1 AND LEN(t.aStringColumn) ),ranked AS ( SELECT *,rnk = ROW_NUMBER() OVER (PARTITION BY aStringColumn,aChar ORDER BY Position) FROM split WHERE aChar = '_' ) SELECT aSubstring = SUBSTRING(first.aStringColumn,first.Position + 1,fifth.Position - first.Position - 1 ) FROM ranked first INNER JOIN ranked fifth ON first.aStringColumn = fifth.aStringColumn WHERE first.rnk = 1 AND fifth.rnk = 5 ;
注意:两种方法都假定每个aStringColumn值至少有5个下划线字符.