sql-server - 当字符串包含空格时 SQL order by 的奇怪行为

标签 sql-server string sql-order-by space

SQL 示例 1:

SELECT TestField 
FROM (VALUES('Ne'), ('NE')) AS TestTable(TestField)
ORDER BY TestField COLLATE Latin1_General_CS_AS

结果1:

Ne  
NE

SQL示例2(NE和a之间有2个空格,而Ne和a之间只有1个):

SELECT TestField 
FROM (VALUES('Ne a'), ('NE  a')) AS TestTable(TestField)
ORDER BY TestField COLLATE Latin1_General_CS_AS

结果2:

NE  a  
Ne a

谁能解释一下吗?

谢谢

最佳答案

第二个查询:

SELECT TestField 
FROM (VALUES
    ('Ne a'), 
    ('NE  a')
--    12345
) AS TestTable(TestField)
ORDER BY TestField COLLATE Latin1_General_CS_AS

对于区分大小写的排序规则,按字母顺序生成的差异(位置 4: <a)比按大小写顺序生成的差异(位置 2: e <E)。因此 NE a 位于 Ne a 之前。

另一个例子:a(位置 2)之间的区别比大小写顺序更重要(位置 1:e E):

SELECT '{' + TestField  + '}'
FROM (VALUES
    ('ea'), 
    ('E ') -- or ('E')
--    12
) AS TestTable(TestField)
ORDER BY TestField COLLATE Latin1_General_CS_AS
/*
TestField
---------
{E }
{ea}
*/

有关 Rusanu 的 blog 的更多详细信息.

更新#1: 您可以使用SQL_EBCDIC037_CP1_CS_AS排序规则:

SELECT TestField 
FROM (VALUES
    ('Ne a'), 
    ('NE  a')
--    12345
) AS TestTable(TestField)
ORDER BY TestField COLLATE SQL_EBCDIC037_CP1_CS_AS
/*
TestField
---------
Ne a
NE  a
*/

但是这种排序规则可能会产生一些奇怪结果。

示例:

SELECT  x.ColA AS ColA_Latin1_General_CS_AS
FROM (
    SELECT  'A'
    UNION ALL 
    SELECT  'AB'
    UNION ALL 
    SELECT  'ABC'
    UNION ALL   
    SELECT  'zzzz'
) x(ColA)
ORDER BY x.ColA COLLATE Latin1_General_CS_AS
/*
ColA_Latin1_General_CS_AS
----------------------------
A
AB
ABC
zzzz
*/

对比

SELECT  x.ColA AS ColA_SQL_EBCDIC037_CP1_CS_AS
FROM (
    SELECT  'A'
    UNION ALL 
    SELECT  'AB'
    UNION ALL 
    SELECT  'ABC'
    UNION ALL   
    SELECT  'zzzz'
) x(ColA)
ORDER BY x.ColA COLLATE SQL_EBCDIC037_CP1_CS_AS
/*
ColA_SQL_EBCDIC037_CP1_CS_AS
----------------------------
zzzz
A
AB
ABC
*/

注意:我从未使用过 SQL_EBCDIC037_CP1_CS_AS 排序规则,因此我不推荐。

更新#2:文本值分为两列(或多列)

-- Scenario #1: before/during insert/update, spaces are trimmed with LTRIM
SELECT TestField1 F1,  TestFiel2 AS F2
FROM (VALUES
    ('JOHN', 'ZOE'),  
    ('JOHN', 'Albano')
) AS TestTable(TestField1, TestFiel2)
ORDER BY TestField1 COLLATE Latin1_General_CS_AS, TestFiel2 COLLATE Latin1_General_CS_AS
/*
F1   F2
---- ------
JOHN Albano
JOHN ZOE
*/
-- Scenario #2: during insert/update spaces are not trimmed (with LTRIM)
SELECT LTRIM(TestField1) COLLATE Latin1_General_CS_AS AS F1,  LTRIM(TestFiel2) COLLATE Latin1_General_CS_AS AS F2
FROM (VALUES
    ('JOHN', ' ZOE'),  -- 1 extra space 
    ('JOHN', 'Albano')
) AS TestTable(TestField1, TestFiel2)
ORDER BY F1, F2 
/*
F1   F2
---- ------
JOHN Albano
JOHN ZOE
*/

注意:我将使用场景#1中描述的解决方案。

关于sql-server - 当字符串包含空格时 SQL order by 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28997747/

相关文章:

sql-server - 如何在sql server 2005中选择包含非英语字符的行(它应该只过滤非英语字符,而不是特殊字符)

android - 带有建议的文本框

c - 更优化的解决方案,查找字符串中子字符串的数量。使用C

ios - 如何从特定位置查找字符串中字符的索引

MySQL group_concat() 按 case 语句值排序

mysql - ORDER BY ... ASC 很慢, "Using index condition"

sql - 替代使用 ROW_NUMBER 以获得更好的性能

asp.net - MSBuild:自动收集数据库迁移脚本?

sql-server - 一个相同列的 SQL 联合

linq-to-sql - LINQ to SQL 在使用 DISTINCT 时不生成 ORDER BY?