postgres中的字母数字案例敏感排序

时间:2013-03-15 08:13:20

标签: postgresql postgresql-9.1

我是postrges的新手,想要对varchar类型列进行排序。想用下面的例子来解释这个问题:

表名:testsorting

   order       name
    1            b
    2            B
    3            a
    4            a1
    5            a11
    6            a2
    7            a20
    8            A
    9            a19

区分大小写的排序(在postgres中是默认排序)给出:

select name from testsorting order by name;

    A
    B
    a
    a1
    a11
    a19
    a2
    a20
    b

案例内容敏感排序提供:

通过UPPER(名称)从测试订单中选择名称;

      A
      a
      a1
      a11
      a19
      a2
      a20
      B
      b

如何在postgres中进行字母数字大小写的敏感内容排序

          a
          A
          a1
          a2
          a11
          a19
          a20
          b
          B

我不介意大写或小写字母的订单,但订单应为“aAbB”或“AaBb”,不应该是“ABab”

请在postgres中建议您是否有任何解决方案。

6 个答案:

答案 0 :(得分:6)

我的PostgreSQL以你想要的方式排序。 PostgreSQL比较字符串的方式由locale和collat​​ion决定。使用createdb创建数据库时,可以使用-l选项设置区域设置。您还可以使用psql -l检查环境中的配置方式:

[postgres@test]$ psql -l
List of databases
 Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
---------+----------+----------+------------+------------+-----------------------
 mn_test | postgres | UTF8     | pl_PL.UTF8 | pl_PL.UTF8 |

如您所见,我的数据库使用波兰语排序规则。

如果使用其他排序规则创建数据库,则可以在查询中使用其他排序规则,如:

SELECT * FROM sort_test ORDER BY name COLLATE "C";
SELECT * FROM sort_test ORDER BY name COLLATE "default";
SELECT * FROM sort_test ORDER BY name COLLATE "pl_PL";

您可以按以下方式列出可用的排序规则:

SELECT * FROM pg_collation;

<强>编辑:

哦,我错过了'a11'必须在'a2'之前。

我不认为标准整理可以解决字母数字排序问题。对于这样的排序,您必须将字符串拆分为部分,就像在Clodoaldo Neto响应中一样。如果您经常需要以这种方式订购,另一个有用的选项是将名称字段分成两列。您可以在INSERT和UPDATE上创建触发器,将name分为name_1name_2,然后:

SELECT name FROM sort_test ORDER BY name_1 COLLATE "en_EN", name_2;

(我将整理从波兰语改为英语,你应该使用你的本地校对来排序像aącć等字母)

答案 1 :(得分:5)

如果名称始终采用1 alpha followed by n numerics格式,则:

select name
from testsorting
order by
    upper(left(name, 1)),
    (substring(name from 2) || '0')::integer

答案 2 :(得分:0)

PostgreSQL使用C库语言环境工具来排序字符串。 C库由主机操作系统提供。在Mac OS X或BSD系列操作系统上,UTF-8语言环境定义被破坏,因此结果按照归类“C”。

image attached for collation results with ubuntu 15.04 as host OS

在postgres wiki上查看常见问题解答以获取更多详细信息:https://wiki.postgresql.org/wiki/FAQ

答案 3 :(得分:0)

this one强烈启发回答 通过使用函数,如果您需要通过不同的查询,它将更容易保持清洁。

CREATE OR REPLACE FUNCTION alphanum(str anyelement)
   RETURNS anyelement AS $$
BEGIN
   RETURN (SUBSTRING(str, '^[^0-9]*'),
      COALESCE(SUBSTRING(str, '[0-9]+')::INT, -1) + 2000000);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

然后你可以这样使用它:

SELECT name FROM testsorting ORDER BY alphanum(name);

测试:

WITH x(name) AS (VALUES ('b'), ('B'), ('a'), ('a1'),
   ('a11'), ('a2'), ('a20'), ('A'), ('a19'))
SELECT name, alphanum(name) FROM x ORDER BY alphanum(name);

 name |  alphanum   
------+-------------
 a    | (a,1999999)
 A    | (A,1999999)
 a1   | (a,2000001)
 a2   | (a,2000002)
 a11  | (a,2000011)
 a19  | (a,2000019)
 a20  | (a,2000020)
 b    | (b,1999999)
 B    | (B,1999999)

答案 4 :(得分:0)

就我而言,我使用了PostgreSQL模块citext,并使用了数据类型CITEXT而不是TEXT。这使得对这些列的排序和搜索都不区分大小写。

可以使用SQL命令CREATE EXTENSION IF NOT EXISTS citext;

安装该模块。

答案 5 :(得分:-2)

我同意Clodoaldo Neto的回答,但也不要忘记添加索引

CREATE INDEX testsorting_name on testsorting(upper(left(name,1)), substring(name from 2)::integer)