2017-07-28 32 views
-1

我需要按數字部分排序查詢。MS Sql按字符串的數字部分排序

我有很多行的樣子:

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

所以,我想第一個數字部分冷杉順序,然後通過第二,然後therd。 想要這樣:

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

我該怎麼做?

UPD:我試過按順序使用PATINDEX函數,但可以想出如何爲所有數字做到這一點。

order by s.product, (case when Patindex('% ,.,-%', s.product)=0 then 0 
         else Cast(SUBSTRING(s.product, Patindex('%[0-9]%', s.product), len(s.product)) as int) end) 
+0

@PeterB心中已經試圖用pathindex功能,可以SE這UPD – Gleb

+0

執行字符串嚴格按照格式4字符後跟一個特殊字符,後跟4個數字,後面跟另一個特殊字符,然後是4個數字agaim? –

+0

分隔符是否始終存在。和 - ? – gbn

回答

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

對於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);