簡體   English   中英

PostgreSQL 受后續字符影響的排序順序

[英]PostgreSQL sort order affected by succeeding characters

我想對test last nametest2 last name進行排序,以便前者出現在后者之前。 我的理解是,每個字符都是從左到右進行比較,直到它們不同,因此第一個不同字符之后的字符不再重要。 但是,如下所示, testtest2之前,但只要我 append 另一個字符,順序就會改變。 為什么會這樣? 我應該使用什么排序規則來獲得所需的訂單? 請注意,將它們轉換為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)

空格是 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"。

這就是自然語言排序的工作原理。 如果要逐個字符進行比較並使空格字符與其他字符一樣,請使用 C 排序規則:

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

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM