我正在使用这个脚本:
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)))
答案 0 :(得分:0)
假设每个值中的唯一数字构成您要排序的数字(而不是在结尾处有数字之前的数字,例如X5Y10
或X5Y10A
) ,那么你最好的办法是在INSERT
/ UPDATE
时间(很少)计算/提取数字部分而不是SELECT
时间(这通常更频繁):< / p>
创建一个UDF dbo.ExtractNumber()
,以提取字符串值的数字部分。虽然UDF通常不太适合性能,但这只会在INSERT
时执行,如果此字段可更新,则可选择在UPDATE
执行。
将非持久计算列添加到名为SortField
(或其他)的表中,并定义为:
dbo.ExtractNumber([SomeString])
在该非持久计算列上创建非聚集索引SortField
。
在您的查询中,执行ORDER BY [SortField]
。
鉴于示例数据全部以X
开头,暗示字符串的alpha部分不相关。如果不是这种情况并且alpha部分是首先排序,然后是数字部分(真正的数字),那么这将需要两个UDF和两个非持久计算列,但是仍然只有一个指数。从技术上讲,UDF可能不需要提取alpha部分,因为它可以是一个简单的SUBSTRING
,从1开始,并使用PATINDEX
找到第一个数字的位置以提供第三个参数SUBSTRING
。