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


12

我有一个数据库,其中的VARCHAR列包含长度可变的整数。我想这样说到10后,9,而不是1对它们进行排序,并70A谈到70后,我是能够做到这一点与PATINDEX() ,热膨胀系数,和CASE语句的WHERE子句。

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


现在,这是该建议的新链接,因为Microsoft已从Connect迁移到UserVoice,但尚未转发URI:支持“自然排序” / DIGITSASNUMBERS作为排序规则选项
Solomon

2
微软表示,如果获得足够的选票,他们将在SQL Server中将其实现为内置功能。因此,请转到此处并单击“投票”按钮
Peter Aylett

Answers:


8

否。排序规则是关于字母排序的,具体取决于代码页,重音符号,大小写,宽度,假名。数字字符(0-9)没有任何属性。

所以9总是之后10B任何种类。

您必须按照说明进行拆分或排序:

ORDER BY
    RIGHT('                              ' + MyColumn, 30)

右边的长度确定您有多少个空格。

您当然可以:

  • 有2列使此操作变得不必要(且速度更快),并有一个计算列将其组合
  • 坚持零
  • 右对齐以char表示(上面我的RIGHT的存储版本)

后两个建议就像我上面的RIGHT,并且略有不同。排序更快(无需处理列项),但需要更多存储空间


我不知道这是如何工作的。它会中断2、2a,3等...
Mladen Prajdic 2011年

@Mladen Prajdic:正确,哎呀。忘记了结尾的字母
-gbn

关于“ 所以9总是后10B在任何类型的。 ”:它只是在SQL Server的方式,因为底层的排序选项来处理‘DigitsAsNumbers’尚未曝光的整理选项。然而;-)。从Windows 7开始,基于Windows的应用程序便可以使用此功能,尤其是在File Explorer中。如果有足够的人支持这一想法,那么有一天它可能会暴露给SQL Server。我试图通过提出以下Connect建议来使事情顺利进行:支持“自然排序” / DIGITSASNUMBERS作为排序规则选项
所罗门·鲁兹基

8

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

CAST( 
     CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then 
         left(OtherColumn,2) 
     else 
         left(otherColumn, 1)  
AS INT)

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


了解类似问题真的很有用。但是,在这种情况下,我无法更改架构。
贾斯汀·迪林

您可以添加到架构吗?除非有计算列,否则您始终可以创建视图-尽管这实际上不会像计算列那样可被优化。
阿龙贝特朗

如果您执行索引视图并具有企业版,则查询可以确定要执行的操作时,查询将自动使用索引视图。如果是标准版,则需要使用WITH(NOEXPAND)来触发要使用的索引视图。到那时,您需要按顺序排列case语句,但是我认为它应该可以工作。
mrdenny

您无需创建计算列。您可以在ORDER BY子句中直接使用该表达式
a_horse_with_no_name 2012年

如果要保证索引或表的扫描,请确保可以。如果您希望能够为该值建立索引,则需要一个计算列或索引视图。
mrdenny 2012年

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;

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


2

是否需要一种明智,有效的方法来将字符串中的数字排序为实际数字?考虑投票支持我的Microsoft Connect建议:支持“自然排序” / DIGITSASNUMBERS作为排序规则选项


尽管此问题特定于SQL Server,而该问题并非如此,但我觉得我仍然应该发布此信息,只是为了提高对此的认识,而不是与任何其他答案相抵触。

话虽这么说,但在SQL Server之外,在某些环境中可以执行这种类型的排序。这是至少在Unicode文档中指定的内容。在UNICODE LOCALE数据标记语言(LDML)第5部分:收集标准/报告中,有一个“ 排序规则设置”图表,其中描述了各种用于定制排序行为的选项。选项之一是-kn-true[numericOrdering on]

如果设置为on,则任何十进制数字序列([ UAX44 ] 中的General_Category = Nd )都将在第一级使用其数字值进行排序。例如,“ A-21” <“ A-123”。计算的主要权重全部在数字重新排序组的开头。因此,对于未经定制的UCA表,“ a $” <“ a0” <“ a2” <“ a12” <“a⓪” <“ aa”。

但是,本文档是“技术标准”,不是核心Unicode规范的一部分。文档顶部的注释说明:

Unicode技术标准(UTS)是独立的规范。符合Unicode标准并不意味着符合任何UTS。

因此,即使两者都符合核心Unicode规范,此特定行为也无法在SQL Server甚至.NET中使用(至少不是本机提供)。

ICU项目(Unicode的国际组件)是一套C / C ++和Java库的实现这个功能,而且还有的甚至一个在线演示。在“相关项目”下,有一个指向.NET项目的链接,该项目似乎是ICU库的COM对象包装,该包装可以使此功能暴露给托管代码。但是尚不清楚该.NET项目是否仍处于活动状态。

但是要查看实际情况,请转到ICU Collat​​ion Demo

将以下内容粘贴到左侧的“ 输入”文本区域中:

1
2
10B
6
11
10A
3
10

将所有选项设置为“默认”。检查sort按钮右侧的“输入行号”选项,并确保未选中“差异强度”选项。

单击sort按钮,您应该返回以下内容:

[1] 1
[8] 10
[6] 10A
[3] 10B
[5] 11
[2] 2
[7] 3
[4] 6

这是在进行典型的字符串排序时应该期望的结果,以及在SQL Server中看到的结果。

现在,在按钮上方的一系列单选按钮中sort,第二行标记为“数字”。选择“打开”单选按钮。

sort再次单击该按钮,您应该返回以下内容:

[1] 1
[2] 2
[7] 3
[4] 6
[8] 10
[6] 10A
[3] 10B
[5] 11

质疑当数字部分位于字符串中间时是否可行?好的,将以下内容粘贴到左侧的“ 输入”文本区域中(替换上一个列表):

Script - 1.sql
Script - 2.sql
Script - 10B.sql
Script - 6.sql
Script - 11.sql
Script - 10A.sql
Script - 3.sql
Script - 10.sql

确保数字设置仍设置为“ on”。sort再次单击该按钮,您应该返回以下内容:

[1] Script - 1.sql
[2] Script - 2.sql
[7] Script - 3.sql
[4] Script - 6.sql
[8] Script - 10.sql
[6] Script - 10A.sql
[3] Script - 10B.sql
[5] Script - 11.sql

想要在另一个地方看到这个吗?在硬盘驱动器上创建一个文件夹,类似于C:\ temp \ sorting \,并创建具有相同“ Script -...”名称的空文件。DIR在命令窗口中执行a ,您将看到标准排序。但是,在Windows资源管理器中查看文件列表时,您会看到使用“数字”选项:-)排序的列表。


仅供参考,Postgres 10支持ICU归类。请参阅Peter Eisentraut的这篇博客文章
罗勒·布尔克

@BasilBourque感谢您提到PG10。最后,该博客文章指出:“ ICU在该领域提供了很多功能,我们尚未通过PostgreSQL公开这些功能。不区分大小写的排序方式,不区分重音的排序方式和完全自定义排序规则的选项。对于将来的Pos​​tgreSQL版本中的用户。” 因此,在第一个/当前的实现中,它不会更改我的答案中的任何信息。如果将来的产品确实允许数字排序,那么我将在答案中提及它,但请作为脚注,因为此问题是特定于SQL Server的。
所罗门·鲁兹基
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.