oro*_*aki 8 postgresql order-by postgresql-9.1 natural-sort
我有一个animal
带有的表name
varchar(255)
,并且我添加了具有以下值的行:
Piranha
__Starts With 2
Rhino
Starts With 1
0_Zebra
_Starts With 1
Antelope
_Starts With 1
Run Code Online (Sandbox Code Playgroud)
当我运行此查询时:
zoology=# SELECT name FROM animal ORDER BY name;
name
-----------------
0_Zebra
Antelope
Piranha
Rhino
_Starts With 1
_Starts With 1
Starts With 1
__Starts With 2
(8 rows)
Run Code Online (Sandbox Code Playgroud)
注意行是如何按顺序排序的,这意味着使用前导_
将_Starts With 1
行放在行之前Starts
,但__
in__Starts With 2
似乎忽略了这一事实,好像2
末尾比前两个字符更重要。
为什么是这样?
如果我用 Python 排序,结果是:
In [2]: for animal in sorted(animals):
....: print animal
....:
0_Zebra
Antelope
Piranha
Rhino
Starts With 1
_Starts With 1
_Starts With 1
__Starts With 2
Run Code Online (Sandbox Code Playgroud)
此外,Python 排序建议下划线在字母之后,这表明 Postgres 对_Starts
行之前的前两行的排序Starts
是不正确的。
注意:我使用的是 Postgres 9.1.15
以下是我尝试查找整理的方法:
zoology=# select datname, datcollate from pg_database;
datname | datcollate
-----------+-------------
template0 | en_US.UTF-8
postgres | en_US.UTF-8
template1 | en_US.UTF-8
zoology | en_US.UTF-8
(4 rows)
Run Code Online (Sandbox Code Playgroud)
和:
zoology=# select table_schema,
table_name,
column_name,
collation_name
from information_schema.columns
where collation_name is not null
order by table_schema,
table_name,
ordinal_position;
table_schema | table_name | column_name | collation_name
--------------+------------+-------------+----------------
(0 rows)
Run Code Online (Sandbox Code Playgroud)
由于您没有为相关列定义不同的排序规则,它使用数据库范围的排序规则,en_US.UTF8
就像在我的测试框中一样。我观察到完全相同的行为,将其视为一种安慰:)
我们看到的显然是变量 collation elements 的一个例子。根据字符和排序规则,许多不同的行为是可能的。这里下划线(以及连字符和其他一些)仅用于打破平局 - 'a' 和 '_a' 在第一轮中是等效的,然后通过考虑下划线来解决它们之间的平局。
如果您想忽略下划线(以及我的示例中的连字符、问号和感叹号)进行排序,您可以定义表达式的排序:
SELECT *
FROM (VALUES ('a'),
('b1'),
('_a'),
('-a'),
('?a'),
('!a1'),
('a2')
) t (val)
ORDER BY translate(val, '_-?!', '');
Run Code Online (Sandbox Code Playgroud)
在我的实验中,向列表中添加新值通常会改变其他相等项之间的顺序,表明它们被真正平等对待。