是否有排序规则按以下顺序 1,2,3,6,10,10A,10B,11 对以下字符串进行排序?

Jus*_*ing 12 sql-server collation sorting natural-sort

我有一个包含不同长度整数的 VARCHAR 列的数据库。我想对它们进行排序,所以 10 在 9 之后,而不是 1,并且 70A 在 70 之后。我可以使用WHERE 子句中的PATINDEX()、CTE 和 CASE 语句来做到这一点。

但是,我想知道是否有不需要的整理。

gbn*_*gbn 8

不。整理是关于字母排序,取决于代码页、重音、大小写、宽度、假名。数字字符 (0-9) 没有任何属性。

所以9总是10B任何形式之后。

您必须按照您的说明将其拆分或按以下方式排序:

ORDER BY
    RIGHT('                              ' + MyColumn, 30)
Run Code Online (Sandbox Code Playgroud)

右边的长度决定了你有多少空间。

你当然可以:

  • 有 2 列使这变得不必要(并且更快)并有一个计算列来组合它们
  • 坚持前导零
  • 在字符中右对齐(上面我的右边的存储版本)

后 2 个建议与我上面的权利相似,但略有不同。排序更快(无需处理 colukmn)但需要更多存储空间


mrd*_*nny 8

我会设置一个计算列,然后根据它进行排序。就像是

CAST( 
     CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then 
         left(OtherColumn,2) 
     else 
         left(otherColumn, 1)  
AS INT)
Run Code Online (Sandbox Code Playgroud)

然后使用此列进行排序,因为您现在可以索引该列。


Aar*_*and 5

如果您想要一种痛苦的方式来证明@gbn 所说的内容(本质上是您不能告诉排序规则以不同的方式对子字符串进行排序),您可以制作一个快速的#temp 表,该表具有您期望的顺序的系数,看看是否按任何排序规则排序返回相同的顺序:

CREATE TABLE #foo(id INT, n NVARCHAR(10));

CREATE TABLE #bar(collation SYSNAME);

SET NOCOUNT ON;

INSERT #foo SELECT 1,'1'
UNION SELECT 2,'2'
UNION SELECT 3,'3'
UNION SELECT 4,'6'
UNION SELECT 5,'10'
UNION SELECT 6,'10A'
UNION SELECT 7,'10B'
UNION SELECT 8,'11';

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'
    WITH x AS 
    (
        SELECT n, rn = ROW_NUMBER() OVER 
        (ORDER BY n COLLATE ' + name + ') FROM #foo
    ) 
    INSERT #bar 
    SELECT TOP (1) ''' + name + ''' FROM x
    WHERE NOT EXISTS
    (
        SELECT COUNT(*) FROM #foo AS f
        WHERE f.id = x.rn
        AND f.n <> x.n
    );' FROM sys.fn_helpcollations();

EXEC sp_executesql @sql;

SELECT collation FROM #bar;

GO
DROP TABLE #foo, #bar;
Run Code Online (Sandbox Code Playgroud)

这会在大约 10 秒内为我运行并产生 0 行 - 这意味着 SQL Server 没有可用的排序规则(至少 2008 R2,还没有尝试过 Denali)将按照您期望的方式进行排序。您需要一种不同的方式来定义排序。