SQL Server:字符串转换数字和排序问题

时间:2014-11-14 14:32:26

标签: sql-server tsql sorting delimiter natural-sort

当我选择时,有一列要显示。

我有一个以下示例代码

C*12:03:01:01
C*12:03:01:02
C*12:03:06
C*12:109
C*12:110
C*12:111
C*12:23

应该有:分隔符。

当它正在排序时,它应该对每个级别进行排序

例如,第一级12,所有相同,所以排序相同 和第二级03,03,23,109,110,111一样,然后是第三......

所以它应该显示如下

C*12:03:01:01
C*12:03:01:02
C*12:03:06
C*12:23
C*12:109
C*12:110
C*12:111

我尝试删除所有字符并仅显示具有以下功能的数字

CREATE FUNCTION [dbo].[fn_StripCharacters]
(
    @String NVARCHAR(MAX), 
    @MatchExpression VARCHAR(255)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    SET @MatchExpression =  '%['+@MatchExpression+']%'

    WHILE PatIndex(@MatchExpression, @String) > 0
        SET @String = Stuff(@String, PatIndex(@MatchExpression, @String), 1, '')

RETURN @String

END

当我尝试

select dbo.fn_StripCharacters(DATA.AlleleName, '^0-9') 
from @temp
where CAST(dbo.fn_StripCharacters(DATA.AlleleName, '^0-9') AS INT)

然后会显示

1223
12109
12110
12111
120306
12030101
12030102

所以我改变主意每个级别(分隔符:)最多只有3个字符。

你们知道如何制作

012:003:001:001
012:003:001:002
012:003:006:000
012:109:000:000
012:110:000:000
012:111:000:000
012:023:000:000

然后如果我删除:并且排序可能会有效。

你们有更好的想法吗?谢谢!

2 个答案:

答案 0 :(得分:1)

在您的示例中,我认为您可以让parsename()为您完成工作:

order by parsename(replace(col, ':', '.'), 4),
         cast(parsename(replace(col, ':', '.'), 3) as int),
         cast(parsename(replace(col, ':', '.'), 2) as int),
         cast(parsename(replace(col, ':', '.'), 1) as int)

你的例子都有四个部分,所以这应该有效。此外,第一个元素(从您的示例中)看起来像是可以按字母顺序排序。

答案 1 :(得分:0)

您可以编写一个函数,该函数将返回在给定位置由特定分隔符分割的字符串的一部分。例如:

alter function [dbo].[f_Split]
    (
        @List nvarchar(max),
        @SplitOn varchar(5),
        @Position int
    )  
    RETURNS nvarchar(250)
    AS  
    BEGIN 
        declare @Index int = 0
        declare @Value nvarchar(250) = ''

        while (Charindex(@SplitOn, @List) > 0) and @Index != @Position
            begin
                set @Value = ltrim(rtrim(substring(@List,1,charindex(@SplitOn,@List)-1)))
                set @List = substring(@List,charindex(@SplitOn,@List)+len(@SplitOn),len(@List))

                set @Position = @Position - 1
            end

        if @Index != @Position
            set @Value = ''

        return @Value
    END

GO

然后您可以在查询中使用它:

declare @temp table (col varchar(50))

insert into @temp (col) values ('C*12:03:01:01')
insert into @temp (col) values ('C*12:03:01:02')
insert into @temp (col) values ('C*12:03:06')
insert into @temp (col) values ('C*12:23')
insert into @temp (col) values ('C*12:109')
insert into @temp (col) values ('C*12:110')
insert into @temp (col) values ('C*12:111')

select 
    *
from 
    @temp 
order by
    dbo.f_split('C*12:03:01:01', ':', 5),
    dbo.f_split('C*12:03:01:01', ':', 4),
    dbo.f_split('C*12:03:01:01', ':', 3),
    dbo.f_split('C*12:03:01:01', ':', 2),
    dbo.f_split('C*12:03:01:01', ':', 1)