我有一个数据库,其中的VARCHAR列包含长度可变的整数。我想这样说到10后,9,而不是1对它们进行排序,并70A谈到70后,我是能够做到这一点与PATINDEX() ,热膨胀系数,和CASE语句的WHERE子句。
但是,我想知道是否有不必要的整理。
我有一个数据库,其中的VARCHAR列包含长度可变的整数。我想这样说到10后,9,而不是1对它们进行排序,并70A谈到70后,我是能够做到这一点与PATINDEX() ,热膨胀系数,和CASE语句的WHERE子句。
但是,我想知道是否有不必要的整理。
Answers:
否。排序规则是关于字母排序的,具体取决于代码页,重音符号,大小写,宽度,假名。数字字符(0-9)没有任何属性。
所以9
总是之后10B
的任何种类。
您必须按照说明进行拆分或排序:
ORDER BY
RIGHT(' ' + MyColumn, 30)
右边的长度确定您有多少个空格。
您当然可以:
后两个建议就像我上面的RIGHT,并且略有不同。排序更快(无需处理列项),但需要更多存储空间
9
总是后10B
在任何类型的。 ”:它只是在SQL Server的方式,因为底层的排序选项来处理‘DigitsAsNumbers’尚未曝光的整理选项。然而;-)。从Windows 7开始,基于Windows的应用程序便可以使用此功能,尤其是在File Explorer中。如果有足够的人支持这一想法,那么有一天它可能会暴露给SQL Server。我试图通过提出以下Connect建议来使事情顺利进行:支持“自然排序” / DIGITSASNUMBERS作为排序规则选项。
CAST(
CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then
left(OtherColumn,2)
else
left(otherColumn, 1)
AS INT)
然后使用此列进行排序,因为您现在可以为该列编制索引。
如果您想以一种痛苦的方式来证明@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)将按照您期望的方式排序。您需要一种不同的方式来定义排序。
尽管此问题特定于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 Collation 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资源管理器中查看文件列表时,您会看到使用“数字”选项:-)排序的列表。