我是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中建议您是否有任何解决方案。
答案 0 :(得分:6)
我的PostgreSQL以你想要的方式排序。 PostgreSQL比较字符串的方式由locale和collation决定。使用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_1
和name_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)