9

看起来 SQL Server(在 2008 R2 上尝试过)正在执行RTRIMon columns inGROUP BY子句。有没有人注意到这一点?我在这里错过了什么吗?

这两个选择在下面的查询中返回相同的结果集,我认为这不应该是这种情况。

declare @t table(Name varchar(100), Age int)
insert into @t values ('A', 20)
insert into @t values ('B', 30)
insert into @t values ('C', 40)
insert into @t values ('D', 25)
insert into @t values (' A', 21)
insert into @t values ('A ', 32)
insert into @t values (' A ', 28)

select
    Name,
    count(*) Count
from @t
group by Name

select
    rtrim(Name) RtrimmedName,
    count(*) Count
from @t
group by rtrim(Name)

请让我知道你的想法...

4

3 回答 3

11

它实际上是在做相反的事情,但可观察到的效果是一样的。

在比较两个长度不等的字符串时,SQL(标准,不仅仅是 SQL Server)的规则之一是较短的字符串用空格填充,直到长度相同,然后进行比较。

如果您想避免感到惊讶,您需要在每个字符串的末尾添加一个非空格字符。


事实上,检查标准文本,似乎有两个选项:

4.6 数据类型的类型转换和混合

...

当比较长度不等的值时,如果用于比较的排序序列具有NO PAD属性,并且较短的值等于较长值的前缀,则认为较短的值小于较长的值。如果用于比较的排序序列具有PAD SPACE属性,则为了比较的目的,较短的值通过右侧 <space> 的连接有效地扩展到较长的长度。

但我知道的所有 SQL Server 排序规则都是PAD SPACE.

于 2012-10-11T07:44:26.833 回答
2

这更容易看到:

declare @t table (Name varchar(100), Age int)
  insert @t values('A', 20),('B', 30),('C', 40),('D  ', 25)
                 ,(' A', 21),('A ', 32),(' A ', 28),('D    ',10);

  select Name, Replace(Name,' ','-'),
         count(*) Count
    from @t
group by Name

--
NAME  COLUMN_1  COUNT
A     -A        2
A     A-        2
B     B         1
C     C         1
D     D--       2

注意 A 和点之间的空格。它选择了 1 空间版本而不是 0 空间版本。
另请注意,D 组选择带有 2 个尾随空格的那个而不是 4 个。

所以,,它没有执行 RTRIM。然而,这有点像一个错误,因为它任意选择两列之一(它首先遇到的那一列)作为 GROUP BY 的结果,如果空格很重要,这可能会让你失望。

于 2012-10-11T08:02:28.757 回答
0

我知道这是一个旧线程,但这可能对其他人有所帮助。我已将以下内容用于 group by 以正确识别尾随空格的差异:

declare @t table(Name varchar(100), Age int)
insert into @t values ('A', 20)
insert into @t values ('B', 30)
insert into @t values ('C', 40)
insert into @t values ('D', 25)
insert into @t values (' A', 21)
insert into @t values ('A ', 32)
insert into @t values (' A ', 28)

select
    Name,
    count(*) Count
from @t
group by Name, DATALENGTH(Name)

通过在组上添加额外的 DATALENGTH,它还将识别项目长度的差异。

于 2019-01-15T17:32:39.993 回答