令人费解的'1' '-'排序,那位高人给解释一下

8992026 2004-04-30 08:45:54
select a='-' into #t
union all select '1'
union all select '--'
union all select '-1'
union all select '1-'
union all select '11'
union all select '---'
union all select '--1'
union all select '-1-'
union all select '-11'
union all select '1--'
union all select '1-1'
union all select '11-'
union all select '111'

select * from #t order by a

drop table #t

结果:
a
----
-
--
---
1
-1
--1
-1-
1-
1--
11
-11
1-1
11-
111

(所影响的行数为 14 行)

为什么这个次序??
...全文
29 点赞 收藏 52
写回复
52 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
8992026 2004-05-05
你提前的太频繁了!!!
回复
8992026 2004-05-04

回复
realgz 2004-04-30
正好 今天接到老板的邮件不爽,走水想问题,拖多爽啊。。。。。。谢谢楼主的题目。
回复
realgz 2004-04-30
有头绪了,确实是2字节到4字节的问题,但是没把机制想清楚,于是是没想好具体证明的查询怎么写,没办法圆满证明。。。。。慢慢想,5.1不还有7天吗,我不急。
回复
8992026 2004-04-30
等ing
回复
realgz 2004-04-30
这样解释不同,但还是觉得我的方向是正确的,分析方法还不够完善,等到晚上我看能不能写个论证出来。
回复
xiao_bai 2004-04-30
来学习一下,我觉得问题出在对中文的处理上,具体怎么排的只有微软知道了
回复
8992026 2004-04-30
结果:
a
----------- ----------- ----------- --------------------
45 32 32 -
45 45 32 --
45 45 45 ---
49 32 32 1
45 49 32 -1
45 45 49 --1
45 49 45 -1-
49 45 32 1-
49 45 45 1--
49 49 32 11
45 49 49 -11
49 45 49 1-1
49 49 45 11-
49 49 49 111

(所影响的行数为 14 行)

回复
8992026 2004-04-30
realgz(realgz) :
你的理论根本就不行,看这个
create table #t(a char(20))
insert #t
select a='-'
union all select '1'
union all select '--'
union all select '-1'
union all select '1-'
union all select '11'
union all select '---'
union all select '--1'
union all select '-1-'
union all select '-11'
union all select '1--'
union all select '1-1'
union all select '11-'
union all select '111'

select unicode(substring(a,1,1)),unicode(substring(a,2,1)),unicode(substring(a,3,1)),* from #t order by a

回复
8992026 2004-04-30
realgz(realgz) :
这样解释不通的
select unicode(substring(a,1,1)),unicode(substring(a,2,1)),unicode(substring(a,3,1)),* from #t order by a

结果:
a 按你的解释
----------- ----------- ----------- ----
45 NULL NULL - 0045
45 45 NULL -- 4545
45 45 45 --- 4545
49 NULL NULL 1 0049
45 49 NULL -1 4945 --关键这一行和下两行
45 45 49 --1 4545
45 49 45 -1- 4945
49 45 NULL 1-
49 45 45 1--
49 49 NULL 11
45 49 49 -11
49 45 49 1-1
49 49 45 11-
49 49 49 111

(所影响的行数为 14 行)
回复
realgz 2004-04-30
可以看见,除非在比较的时候是2D31和31比,否则没有可能 2D>31
所以你的字段如果足够长,理论上就没有这个问题了。
回复
8992026 2004-04-30
分大把,看来现在结论只能是用Chinese_PRC_CI_AS排序规则的时候要小心点

回复
realgz 2004-04-30
-1 2D 31
1 31
10 31 30
11 31 31
可以看到,以上字符的二进制表示
唯一的合理解释似乎是在中文状态下用4个字节表示一个字符,所以 SQL 自动取每4个字节进行比较
if '-1'>'1' COLLATE SQL_Latin1_General_Cp437_CS_AS
print 'surprise! -1>1'
使用2个字节的排序规则自然搞定

if '-1'>'1' COLLATE Chinese_Taiwan_Stroke_CI_AS
print 'surprise! -1>1'
4字节的就有问题 搞定1
回复
txlicenhe 2004-04-30
偶来看看有没有分剩下。
回复
outwindows 2004-04-30
Chinese_PRC_CI_AS
回复
8992026 2004-04-30
order by replace(a,'-','0')
可以解决,只可惜索引白建了
回复
JerryOne 2004-04-30
目前还没有遇见过这样的问题!
Mark
回复
outwindows 2004-04-30
gz...
回复
realgz 2004-04-30
if '-1'>'1' COLLATE Chinese_PRC_CI_AS
print 'surprise! -1>1'

if '-1'>'10' COLLATE Chinese_PRC_CI_AS
print 'surprise! -1>10'
回复
pbsql 2004-04-30
想了半天,可能是SQL将“-”当成通配符了,所以“-”可能排在“1”前面也可能在后面

这样可以避免:(“0”可以由不引起歧义的任意字符代替)
order by replace(a,'-','0')
回复
发动态
发帖子
疑难问题
创建于2007-09-28

2.1w+

社区成员

MS-SQL Server 疑难问题
申请成为版主
社区公告
暂无公告