我需要按数字部分订购我的查询。
我有很多行看起来像:
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'
答案 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);