PostgreSQL排序顺序受后续字符影响

oalqel3c  于 2023-02-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(142)

我想对test last nametest2 last name进行排序,使前者排在后者之前。我的理解是,每个字符都是从左到右进行比较的,直到它们不同为止,因此,第一个不同字符之后的字符不再重要。然而,如下所示,test排在test2之前,但只要我追加了另一个字符,顺序发生了变化。为什么会发生这种情况?我应该使用什么排序规则来获得所需的顺序?注意,将它们转换为bytea将产生所需的顺序。

test=# SELECT 'test last name' < 'test2 last name' COLLATE "en_US";
 ?column?
----------
 f
(1 row)

test=# SELECT 'test last' < 'test2 last' COLLATE "en_US";
 ?column?
----------
 f
(1 row)

test=# SELECT 'test ' < 'test2 ' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test ' < 'test2' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test' < 'test2' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test  ' < 'test2' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test  ' < 'test2 ' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test  ' < 'test2  ' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test  ' < 'test2 ' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test  ' < 'test2 l' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test ' < 'test2 l' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test l' < 'test2 l' COLLATE "en_US";
 ?column?
----------
 f
(1 row)

test=# SELECT 'test l' < 'test2l' COLLATE "en_US";
 ?column?
----------
 f
(1 row)

test=# SELECT 'test ' < 'test2l' COLLATE "en_US";
 ?column?
----------
 t
(1 row)

test=# SELECT 'test last name'::bytea < 'test2 last name'::bytea;
 ?column? 
----------
 t
(1 row)
6ojccjat

6ojccjat1#

白色是ICU排序规则中的特殊字符。
参见演示:https://www.unicode.org/reports/tr10/#Variable_Weighting_Examples
另请访问:http://www.unicode.org/reports/tr35/tr35-collation.html#table-collation-settings
简单解释:https://unicode-org.github.io/icu/userguide/collation/customization/ignorepunct.html#shift-trimmed
您可以进行以下测试:

CREATE COLLATION coll_shifted(provider = icu, locale = 'en-u-ka-shifted');
CREATE COLLATION coll_noignore(provider = icu, locale = 'en-u-ka-noignore');

SELECT 'test last name' < 'test2 last name' COLLATE coll_shifted
union all
SELECT 'test last name' < 'test2 last name' COLLATE coll_noignore
union all
SELECT 'test last name' < 'test2 last name' COLLATE "en_US";

如果你只想通过代码指针进行比较,你可以使用COLLATE“C”或者COLLATE“POSIX”。

agyaoht7

agyaoht72#

这就是自然语言排序规则的工作原理。如果您希望逐个字符进行比较,并使空格字符与其他字符一样,请使用C排序规则:

SELECT 'test last name' < 'test2 last name' COLLATE "C";

 ?column? 
══════════
 t
(1 row)

但是不要抱怨如果'Z' < 'a' ...

相关问题