MS Sql顺序由字符串的数字部分组成

时间:2017-07-28 08:30:54

标签: sql sql-server tsql sql-server-2008-r2

我需要按数字部分订购我的查询。

我有很多行看起来像:

Article7
Articke8
Article3
Article4

所以,我希望第一个数字部分的第一个顺序,然后是第二个,然后是第二个。 像这样:

'ABCD.1234.567'
'ABCD.1234-2345'
'ABCD.1234.1213.1'

我该怎么做?

UPD:我尝试按顺序使用PATINDEX函数,但可以弄清楚如何为所有数字执行此操作。

'ABCD.1234.567'
'ABCD.1234.1213.1'
'ABCD.1234-2345'

2 个答案:

答案 0 :(得分:1)

您可以使用字符串拆分功能

DECLARE @SampleData AS TABLE
(
    Name varchar(100)
)

INSERT INTO @SampleData
VALUES
('ABCD.1234.567'),
('ABCD.1234-2345'),
('ABCD.1234.1213.1')

您的查询将是

SELECT *
FROM @SampleData sd
OUTER APPLY
(
    SELECT CAST(t.Value AS int) AS Part1
    FROM [dbo].[SplitString](replace(sd.Name,'-', '.'),'.') t
    WHERE t.Pos = 2
) p1
OUTER APPLY
(
    SELECT CAST(t.Value AS int) AS Part2
    FROM [dbo].[SplitString](replace(sd.Name,'-', '.'),'.') t
    WHERE t.Pos = 3
) p2
OUTER APPLY
(
    SELECT CAST(t.Value AS int) AS Part3
    FROM [dbo].[SplitString](replace(sd.Name,'-', '.'),'.') t
    WHERE t.Pos = 4
) p3
ORDER BY p1.[Part1], p2.[Part2], p3.Part3

字符串拆分功能

CREATE FUNCTION [dbo].[SplitString] (@Text varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
   Select Pos = Row_Number() over (Order By (Select null))
        ,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
   From (Select x = Cast('<x>'+ Replace(@Text,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
   Cross Apply x.nodes('x') AS B(i)
);

结果:

Name              Part1  Part2  Part3
---------------------------------------
ABCD.1234.567     1234   567    NULL
ABCD.1234.1213.1  1234   1213   1
ABCD.1234-2345    1234   2345   NULL

答案 1 :(得分:1)

对于4组或更少的组,PARSENAME提供了很好的字符串拆分功能

DECLARE @foo TABLE (foo varchar(100));
INSERT @foo
VALUES
('ABCD.1234.567'),
('ABCD.1234-2345'),
('ABCD.1234.1213.1')

SELECT
    Y.foo
FROM
    (
    SELECT 
        Element1 = REVERSE(PARSENAME(X.ProcessedFoo, 1)),
        Element2 = REVERSE(PARSENAME(X.ProcessedFoo, 2)),
        Element3 = REVERSE(PARSENAME(X.ProcessedFoo, 3)),
        Element4 = REVERSE(PARSENAME(X.ProcessedFoo, 4)),
        X.foo
    FROM
        (
        SELECT 
            foo, 
            ProcessedFoo = REVERSE(REPLACE(foo, '-', '.'))
        FROM @foo 
        ) X
    ) Y
ORDER BY
    Y.Element1, 
    CAST(Y.Element2 AS int), 
    CAST(Y.Element3 AS int), 
    CAST(Y.Element4 AS int);