【问题标题】:Strange sort behaviour for numeric values in Varchar column in SQL ServerSQL Server 中 Varchar 列中数值的奇怪排序行为
【发布时间】:2019-06-29 01:44:26
【问题描述】:

谁能解释一下这种奇怪的行为:

select a from (
    select '1' as a
    union all
    select '2' as a
    union all
    select '-3' as a
) as b
order by a desc

select a from (
    select '4' as a
    union all
    select '5' as a
    union all
    select '-3' as a
) as b
order by a desc

查询 1 的结果:

-3
2
1

查询 2 的结果:

5
4
-3

看起来- 字符被忽略了。不过,我认为 SQL Server 会根据 ASCII 代码订购 varchars。

所以预期的结果是:

2
1
-3   //ascii - is before 0-9

和:

 5
 4
-3  //ascii - is before 0-9

如果我在数字前添加一个字母,我会得到相同的结果:

select a from (
    select 'a1' as a
    union all
    select 'a2' as a
    union all
    select '-a3' as a
) as b
order by a desc

select a from (
    select 'a4' as a
    union all
    select 'a5' as a
    union all
    select '-a3' as a
) as b
order by a desc

【问题讨论】:

  • 我怀疑排序规则设置很重要。使用您定义的显式数字 SortOrder 列来控制排序顺序几乎总是更好。
  • SQL Sorting and hyphens 可能重复?
  • 那些字符串是字符串,不是数值。
  • 字符串值 '1000' 将排在 '9' 之前,而数值 9 将排在 1000 之前。
  • @Makla:我已经检查了您的查询,它给了我完美的结果

标签: sql sql-server tsql


【解决方案1】:

SQL Server 中的实际排序顺序完全取决于活动的collation(默认值或明确指定的排序规则)。

如果例如你使用二进制排序规则,你会得到你对这种情况的期望:

select a from (
    select '1' as a
    union all
    select '2' as a
    union all
    select '-3' as a
) as b
order by a COLLATE Latin1_General_BIN desc
/* Result: 2, 1, -3  */

select a from (
    select '4' as a
    union all
    select '5' as a
    union all
    select '-3' as a
) as b
order by a COLLATE Latin1_General_BIN desc
/* Result: 5, 4, -3  */

要查看所有排序规则,请运行以下命令:

select * from sys.fn_helpcollations()

【讨论】:

  • 感谢@PeterB,如果能解释一下(分享链接)为什么二进制排序规则的行为会如此,那就太好了。 (如果我找到了,我会尝试自己添加这些信息。)
  • 这是一篇关于二进制排序规则的更多信息的文章:mikerodionov.com/2018/06/sql-servers-binary2-collations
【解决方案2】:

您应该像这样将排序规则设置为 Latin1_General_BIN:

select a from (
select '1' as a
union all
select '0' as a
union all
select '-1' as a
) as b
order by a COLLATE Latin1_General_BIN desc

【讨论】:

  • 这与 Peter B 的答案有何不同?
【解决方案3】:

如果你使用数字而不是字符串...

select a from (
    select 1 as a
    union all
    select 2 as a
    union all
    select -3 as a
) as b
order by a desc

...然后数字按预期排序:

2
1
-3

【讨论】:

  • 当然可以,但我没有号码。我也没有值 2、3 和 -1。这是一个简化的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 2011-03-04
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多