2016-01-20 152 views
3

我有以下SQL:如何按数字顺序对字母数字SQL Server NVARCHAR列进行排序?

SELECT fldTitle 
FROM tblTrafficAlerts 
ORDER BY fldTitle 

它返回下列顺序的结果(从NVARCHAR列):

A1M northbound within J17 Congestion 
M1 J19 southbound exit Congestion 
M1 southbound between J2 and J1 Congestion 
M23 northbound between J8 and J7 Congestion 
M25 anti-clockwise between J13 and J12 Congestion 
M25 clockwise between J8 and J9 Broken down vehicle 
M3 eastbound at the Fleet services between J5 and J4A Congestion 
M4 J19 westbound exit Congestion 

你会看到M23和M25是在M3以上所列和M4行,这看起来并不令人满意,而且如果扫描更长的结果列表,您不希望按照此顺序读取它们。

所以我想按字母顺序排序,然后数值结果,看起来像:

A1M northbound within J17 Congestion 
M1 J19 southbound exit Congestion 
M1 southbound between J2 and J1 Congestion 
M3 eastbound at the Fleet services between J5 and J4A Congestion 
M4 J19 westbound exit Congestion 
M23 northbound between J8 and J7 Congestion 
M25 anti-clockwise between J13 and J12 Congestion 
M25 clockwise between J8 and J9 Broken down vehicle 

因此M3和M4出现上述M23和M25。

+0

标签DBMS。 (答案可能取决于使用的产品。) – jarlh

+0

Microsoft SQL Server 2008 - 感谢您的标签编辑建议! – Rich

+2

@JaydipJ该运营商尚未表示未按预期工作。他问的是如何排序与默认 –

回答

2

这应该处理它。还添加了一些奇怪的数据,以确保排序也适用于认为:

SELECT x 
FROM 
(values 
('A1M northbound within J17 Congestion'), 
('M1 J19 southbound exit Congestion'), 
('M1 southbound between J2 and J1 Congestion'), 
('M23 northbound between J8 and J7 Congestion'), 
('M25 anti-clockwise between J13 and J12 Congestion'), 
('M25 clockwise between J8 and J9 Broken down vehicle'), 
('M3 eastbound at the Fleet services between J5 and J4A Congestion'), 
('M4 J19 westbound exit Congestion'),('x'), ('2'), ('x2')) x(x) 
ORDER BY 
    LEFT(x, patindex('%_[0-9]%', x +'0')), 
    0 + STUFF(LEFT(x, 
    PATINDEX('%[0-9][^0-9]%', x + 'x1x')),1, 
    PATINDEX('%_[0-9]%', x + '0'),'') 

结果:使用

2 
A1M northbound within J17 Congestion 
M1 J19 southbound exit Congestion 
M1 southbound between J2 and J1 Congestion 
M3 eastbound at the Fleet services between J5 and J4A Congestion 
M4 J19 westbound exit Congestion 
M23 northbound between J8 and J7 Congestion 
M25 anti-clockwise between J13 and J12 Congestion 
M25 clockwise between J8 and J9 Broken down vehicle 
x 
x2 
+0

这完美的作品,谢谢!为了完整起见,我的结果查询是:SELECT fldTitle FROM tblTrafficAlerts ORDER BY LEFT(fldTitle,PATINDEX('%_ [0-9]%',fldTitle +'0')),0 + STUFF(LEFT(fldTitle, PATINDEX('%[0-9] [^ 0-9]%',fldTitle +'x1x')),1,PATINDEX('%_ [0-9]%',fldTitle +'0'),'' ) – Rich

0

也许这并不漂亮,但它的工作:

DECLARE @tblTrafficAlerts TABLE 
(
    fldTitle NVARCHAR(500) 
); 

INSERT INTO @tblTrafficAlerts (fldTitle) 
VALUES (N'A1M northbound within J17 Congestion') 
    , (N'M1 J19 southbound exit Congestion') 
    , (N'M1 southbound between J2 and J1 Congestion') 
    , (N'M23 northbound between J8 and J7 Congestion') 
    , (N'M25 anti-clockwise between J13 and J12 Congestion') 
    , (N'M25 clockwise between J8 and J9 Broken down vehicle') 
    , (N'M3 eastbound at the Fleet services between J5 and J4A Congestion') 
    , (N'M4 J19 westbound exit Congestion'); 

SELECT * 
FROM @tblTrafficAlerts AS T 
CROSS APPLY (SELECT PATINDEX('%[0-9]%', T.fldTitle)) AS N(NumIndex) 
CROSS APPLY (SELECT PATINDEX('%[0-9][^0-9]%', T.fldTitle)) AS NN(NextLetter) 
ORDER BY SUBSTRING(T.fldTitle, 0, N.NumIndex), CONVERT(INT, SUBSTRING(T.fldTitle, N.NumIndex, NN.NextLetter - 1)); 

这将提取之前的一切第一号,为了通过它,然后用它提取数量和顺序为整数。

这是输出:

╔══════════════════════════════════════════════════════════════════╗ 
║        fldTitle        ║ 
╠══════════════════════════════════════════════════════════════════╣ 
║ A1M northbound within J17 Congestion        ║ 
║ M1 J19 southbound exit Congestion        ║ 
║ M1 southbound between J2 and J1 Congestion      ║ 
║ M3 eastbound at the Fleet services between J5 and J4A Congestion ║ 
║ M4 J19 westbound exit Congestion         ║ 
║ M23 northbound between J8 and J7 Congestion      ║ 
║ M25 anti-clockwise between J13 and J12 Congestion    ║ 
║ M25 clockwise between J8 and J9 Broken down vehicle    ║ 
╚══════════════════════════════════════════════════════════════════╝ 
0
SELECT fldTitle FROM tblTrafficAlerts order by LEFT(fldTitle , CHARINDEX(' ', fldTitle) - 1), fldTitle 

或使用patindex

ORDER BY LEFT(Col1,PATINDEX('%[^0-9]%',Col1)-1) 
0

我想是这样的:

编辑:我有两种portiions分离这样的:首字母和第二部分。这可以让你 - 如果需要的话 - - 以数字方式处理第二部分(但第一行有一个令人不安的“M”......)

第二步操作会更容易: ,检查长度并在需要时在排序上添加'0'。

DECLARE @tblTrafficAlerts TABLE(fldTitle VARCHAR(500)); 

INSERT INTO @tblTrafficAlerts VALUES 
('A1M northbound within J17 Congestion') 
,('M1 J19 southbound exit Congestion') 
,('M1 southbound between J2 and J1 Congestion') 
,('M23 northbound between J8 and J7 Congestion') 
,('M25 anti-clockwise between J13 and J12 Congestion') 
,('M25 clockwise between J8 and J9 Broken down vehicle') 
,('M3 eastbound at the Fleet services between J5 and J4A Congestion') 
,('M4 J19 westbound exit Congestion'); 

SELECT ta.fldTitle 
     ,Leading.Letter 
     ,Leading.SecondPart 
FROM @tblTrafficAlerts AS ta 
CROSS APPLY(SELECT SUBSTRING(ta.fldTitle,1,1) AS Letter 
        ,SUBSTRING(ta.fldTitle,2,CHARINDEX(' ',ta.fldTitle)-1) AS SecondPart) AS Leading 
ORDER BY Leading.Letter,CASE WHEN LEN(Leading.SecondPart)=1 THEN Leading.SecondPart + '0' ELSE Leading.SecondPart END 

结果:

fldTitle               Letter SecondPart 
A1M northbound within J17 Congestion        A  1M 
M1 J19 southbound exit Congestion         M  1 
M1 southbound between J2 and J1 Congestion       M  1 
M23 northbound between J8 and J7 Congestion      M  23 
M25 anti-clockwise between J13 and J12 Congestion     M  25 
M25 clockwise between J8 and J9 Broken down vehicle    M  25 
M3 eastbound at the Fleet services between J5 and J4A Congestion M  3 
M4 J19 westbound exit Congestion         M  4