PostgreSQL排序错误



我使用PostgreSQL 9.3.3,我有一个表,一列名为title(字符变化(50))。

当我执行了以下查询:

select * from test
order by title asc

我得到了以下结果:

#
A
#Example

为什么"#Example"在最后一个位置?在我看来"#Example"应该放在第二个位置

文本(包括charvarchar以及text类型)的排序行为取决于您的区域设置的当前排序

参见前面密切相关的问题:

    <
  • PostgreSQL类/gh>
  • https://stackoverflow.com/q/21006868/398670

如果希望按照ASCII值进行简单排序,而不是按照本地语言规则进行适当的本地化排序,则可以使用COLLATE子句

select * 
from test
order by title COLLATE "C" ASC

或全局更改数据库排序(需要转储和重新加载,或完全重新索引)。在我的Fedora 19 Linux系统上,我得到以下结果:

regress=> SHOW lc_collate;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)
regress=> WITH v(title) AS (VALUES ('#a'), ('a'), ('#'), ('a#a'), ('a#')) 
          SELECT title FROM v ORDER BY title ASC;
 title 
-------
 #
 a
 #a
 a#
 a#a
(5 rows)
regress=> WITH v(title) AS (VALUES ('#a'), ('a'), ('#'), ('a#a'), ('a#')) 
          SELECT title FROM v ORDER BY title COLLATE "C" ASC;
 title 
-------
 #
 #a
 a
 a#
 a#a
(5 rows)

PostgreSQL使用操作系统的排序支持,因此结果可能因主机操作系统的不同而略有不同。特别是,至少某些版本的Mac OS X已经严重破坏了unicode排序处理。

似乎,当排序Oracle以及Postgres时,只需忽略 非alpha数字字符,例如

  select '*' 
   union all
  select '#' 
   union all
  select 'A'
   union all
  select '*E'
   union all
  select '*B'
   union all
  select '#C'
   union all
  select '#D'
order by 1 asc

返回(看:DBMS 不注意在'A'. 'E'之前的前缀)

  *
  #
  A
  *B
  #C
  #D
  *E

在你的例子中,Postgres实际上排序的是

'''A''Example'

如果你把'#'放在字符串的中间,行为将是相同的:

  select 'A#B'
   union all
  select 'AC'
   union all
  select 'A#D'  
   union all
  select 'AE' 
order by 1 asc

返回(忽略#,因此实际上比较'AB', 'AC', 'AD''AE')

  A#B
  AC
  A#D
  AE

更改的比较规则,您应该使用排序,例如

  select '#' collate "POSIX"
   union all
  select 'A' collate "POSIX"
   union all
  select '#Example' collate "POSIX"
order by 1 asc

返回(在您的情况下需要)

  #
  #Example
  A

最新更新