【问题标题】:PostgreSQL incorrect sortingPostgreSQL 不正确的排序
【发布时间】:2017-10-11 23:06:27
【问题描述】:

我使用 PostgreSQL 9.3.3,并且我有一个表,其中有一列名为标题(字符变化(50))。

当我执行了以下查询时:

select * from test
order by title asc

我得到了以下结果:

#
A
#Example

为什么“#Example”在最后一个位置?在我看来,“#Example”应该排在第二位。

【问题讨论】:

  • 这是一个 SQL Fiddle:sqlfiddle.com/#!15/d819d/1.
  • @GordonLinoff:我在 SQL Server 2008 R2 上对其进行了测试,#Example 在第二行中符合预期
  • title 列的数据类型是什么?
  • 哇,在 Gordon 的 sqlfiddle 中添加 desc 会生成 '#Example'、'A'、'#'
  • Oracle 11.2 返回相同的错误顺序

标签: sql postgresql


【解决方案1】:

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

查看之前密切相关的问题:

如果您想按 ASCII 值进行简单排序,而不是按照当地语言规则正确本地化排序,you can use the COLLATE clause

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 排序规则处理。

【讨论】:

    【解决方案2】:

    看来,当对 OraclePostgres 进行排序时,只需 ignore non alpha numeric chars,例如

      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'

    如果您将'#' 放在字符串的中间 od,则行为将相同

      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
    

    改变你应该使用collat​​ion的比较规则,例如

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

    返回(根据您的情况)

      #
      #Example
      A
    

    【讨论】:

    • 但是这会首先使用哈希对 '#A'、'C'、'#B' 进行排序。
    • @Glenn:是的,'#' 被忽略,'#A'、'C'、'#B' 被排序,因为它们应该是 '#A'、'#B'、'C' (因为'A'
    • 这取决于数据库的排序规则。当我在本地数据库(使用 UTF8 和德语排序规则)上运行您的语句时,按以下顺序获取结果:#,#C,#D,*,*B,*E,A
    猜你喜欢
    • 1970-01-01
    • 2021-10-26
    • 2012-05-19
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多