订购以数字结尾的字符串,但有一些例外以非数字字符结尾

时间:2016-02-20 17:40:41

标签: sql-server tsql sql-server-2014

我正在使用这个脚本:

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp

CREATE TABLE #Temp
(
    SomeString NVARCHAR(10)
)

INSERT INTO #Temp
SELECT 'X1'
    UNION 
SELECT 'X10'
    UNION 
SELECT 'X2'

-- undesired result
SELECT * FROM #Temp ORDER BY SomeString

-- desired result
SELECT * FROM #Temp 
ORDER BY LEFT(SomeString,PATINDEX('%[0-9]%',SomeString)-1), -- alphabetical sort 
CONVERT(INT,SUBSTRING(SomeString,PATINDEX('%[0-9]%',SomeString),LEN(SomeString))) -- numerical sort

详情请见:http://www.essentialsql.com/use-sql-server-to-sort-alphanumeric-values/

实现明智的秩序'像这样(见声明预期结果):

X1
X2
X10

不幸的是,如果原始字符串包含任何不以数字结尾的内容(罕见的例外),则不起作用。换言之,在这种情况下:

INSERT INTO #Temp
SELECT 'X1'
    UNION 
SELECT 'X10'
    UNION 
SELECT 'X2'
    UNION 
SELECT 'X2a'

PS:

可能的原油解决方案:

SELECT * FROM #Temp 
ORDER BY LEFT(SomeString,PATINDEX('%[0-9]',CASE WHEN SomeString LIKE '%[a-Z]' THEN SomeString + '0' ELSE SomeString END)-1), -- alphabetical sort 
CONVERT(INT,SUBSTRING(SomeString,PATINDEX('%[0-9]',CASE WHEN SomeString LIKE '%[a-Z]' THEN SomeString + '0' ELSE SomeString END),LEN(SomeString)))

1 个答案:

答案 0 :(得分:0)

假设每个值中的唯一数字构成您要排序的数字(而不是在结尾处有数字之前的数字,例如X5Y10X5Y10A) ,那么你最好的办法是在INSERT / UPDATE时间(很少)计算/提取数字部分而不是SELECT时间(这通常更频繁):< / p>

  1. 创建一个UDF dbo.ExtractNumber(),以提取字符串值的数字部分。虽然UDF通常不太适合性能,但这只会在INSERT时执行,如果此字段可更新,则可选择在UPDATE执行。

  2. 将非持久计算列添加到名为SortField(或其他)的表中,并定义为:

    dbo.ExtractNumber([SomeString])
    
  3. 在该非持久计算列上创建非聚集索引SortField

  4. 在您的查询中,执行ORDER BY [SortField]

  5. 鉴于示例数据全部以X开头,暗示字符串的alpha部分不相关。如果不是这种情况并且alpha部分首先排序,然后是数字部分(真正的数字),那么这将需要两个UDF和两个非持久计算列,但是仍然只有一个指数。从技术上讲,UDF可能不需要提取alpha部分,因为它可以是一个简单的SUBSTRING,从1开始,并使用PATINDEX找到第一个数字的位置以提供第三个参数SUBSTRING