获取从 split_string 中提取的每个字符串的排名

Get the rank of each string extracted from split_string

我有一个 TABLE 和 STR DNA DATA 以下 Table [DYS]


Id DYS385
3 10-19
4 13-16
5 13-18
6 13-19
7 13-17
8 13-18
9 13-18
10 14-19
11 13-19
12 13-18

我正在使用以下脚本拆分 [DYS385]

的值
select top 10 id,[DYS385],t.Value 
from dys 
OUTER APPLY(select * from string_split([DYS385],'-')) t
where dys385 is not null

输出


Id DYS385 VALUE
3 10-19 10
3 10-19 19
4 13-16 13
4 13-16 16
5 13-18 13
5 13-18 18
6 13-19 13
6 13-19 19
7 13-17 13
7 13-17 17

我想为每个值获取排名 例子 10-19 => 10: 排名 1, 19: 排名 2

期望的结果:


Id DYS385 VALUE RANK
3 10-19 10 1
3 10-19 19 2
4 13-16 13 1
4 13-16 16 2
5 13-18 13 1
5 13-18 18 2
6 13-19 13 1
6 13-19 19 2
7 13-17 13 1
7 13-17 17 2

Split_string 有一个选项可以输出这个排名,称为序数。只需添加一个值为 1 的额外参数:

SELECT *FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ', 1);

那个returns:

value   ordinal
Lorem   1
ipsum   2
dolor   3
sit 4
amet.   5

在您的情况下,查询将是:

select top 10 id,[DYS385],t.* from dys OUTER APPLY(select * from string_split([DYS385],'-',1)) t where dys385 is not null

使用替代 string-split 方法,例如 XML 或 Json 可以 return 一个序数位置,例如:

create function dbo.SplitString(@string varchar(1000), @Delimiter varchar(10))
returns table
as
   return(  
      select j.[value], 1 + Convert(tinyint,j.[key]) Seq 
      from OpenJson(Concat('["',replace(@string,@delimiter, '","'),'"]')) j
   );


select value, Seq as [Rank]
from dbo.SplitString('10-19','-')
order by [Rank];

Example fiddle

鉴于此数据:

CREATE TABLE dbo.Something(Id int, DYS385 varchar(10));

INSERT dbo.Something(Id, DYS385) VALUES (3 , '10-19'), 
(4 , '13-16'), (5 , '13-18'), (6 , '13-19'),
(7 , '13-17'), (8 , '13-18'), (9 , '13-18'),
(10, '14-19'), (11, '13-19'), (12, '13-18');

确保按正确顺序排列 broken-up 字符串的另一种方法是使用 PARSENAME() 等技巧,尽管这可能对字符串长度以及点是否在其中有效很敏感数据:

SELECT s.Id, s.DYS385, value = v.v, [rank] = ROW_NUMBER() OVER 
  (PARTITION BY s.Id ORDER BY c.c DESC)
FROM dbo.Something AS s
CROSS APPLY (VALUES(1),(2)) AS c(c)
CROSS APPLY (VALUES(PARSENAME(REPLACE(s.DYS385,'-','.'),c.c))) AS v(v)
ORDER BY s.Id, [rank];

输出:

Id DYS385 value rank
3 10-19 10 1
3 10-19 19 2
4 13-16 13 1
4 13-16 16 2
5 13-18 13 1
5 13-18 18 2
6 13-19 13 1
6 13-19 19 2
7 13-17 13 1
7 13-17 17 2
8 13-18 13 1
8 13-18 18 2
9 13-18 13 1
9 13-18 18 2
10 14-19 14 1
10 14-19 19 2
11 13-19 13 1
11 13-19 19 2
12 13-18 13 1
12 13-18 18 2

我们还可以让recursivesplit_string函数returns对每一项的排序如下 Link dbfiddle

Create function Split_Recursive(@string nvarchar(max),@delimiter as varchar(1)) returns Table
as
return(
with cte as(
select 1 N,
case when charindex(@delimiter,@string,1) =0 then @string else
substring(@string,1,-1+charindex(@delimiter,@string,1)) end [Found],
case when charindex(@delimiter,@string,1)=0 then @string else substring(@string,1+charindex(@delimiter,@string,1) ,len(@string)) 
end [MYSTRING]
union all
select 1+n,
case when charindex(@delimiter,[MYSTRING],1)=0 then [MYSTRING] else
substring([MYSTRING],1,-1+charindex(@delimiter,[MYSTRING],1)) end,substring([MYSTRING],1+charindex(@delimiter,[MYSTRING]),len([MYSTRING])) from cte
where charindex(@delimiter,[MYSTRING],1)>0),
cte2 as (select N,Found from cte 
union select 1+t.N,Mystring from cte OUTER APPLY(select top 1 N from cte order by n desc)t where t.n=cte.n
)
select N Rank,Found from cte2
)

go

select * from dbo.Split_Recursive('12-16','-')

输出


Rank Found
1 12
2 16