提问人:va. 提问时间:10/13/2023 更新时间:10/20/2023 访问量:142
PostgreSQL 中的重音区分排序
Accent sensitive sort in PostgreSQL
问:
如何按拉脱维亚语字母顺序对PostgreSQL中的文本进行排序,因此任何没有重音的字母总是在有重音的字母之前?
例如,这个
select * from (
select 'bā' as name
union select 'āa'
union select 'ac'
union select 'Āb'
union select 'Ā'
) t
order by name COLLATE "lv-x-icu"
返回Ā āa Āb ac bā
但预期的结果是ac Ā āa Āb bā
我尝试创建一些自定义排序规则,但它们都没有返回预期的结果。
答:
这是一个不寻常的要求。在自然语言排序规则(包括拉图维亚排序规则)中,字符串按不同的步骤进行比较:
在第一步中,标点符号、大小写和重音符号将被忽略。如果字符串比较不同,则决定了排序顺序。这称为初级差异。
如果字符串在主要级别上相等,则仅忽略标点符号和大小写,但重音很重要。如果字符串比较不同,则决定了排序顺序。这是中学阶段的区别。
如果字符串在二级上相等,则仅忽略标点符号,但重音和大小写很重要。这是高等教育。
最后,如果字符串在三级水平上相等,则标点符号(四级)的差异很重要。
这解释了你看到的排序顺序:因为在初级阶段,口音没有被考虑在内。a < aa < ab < ac <ba
如果你愿意,你希望重音在初级上被认为是不同的,就好像 和 是不同的字母一样。为此,您必须使用 ICU 排序规则并使用其他规则对其进行自定义。这只能从 v16 开始实现:ac < Ā
a
ā
CREATE COLLATION latuvian_custom (
PROVIDER = icu,
LOCALE = 'lv',
RULES = '& a < ā & A < Ā & c < č & C < Č & e < ē & E < Ē & g < ģ & G < Ģ & k < ķ & K < Ķ & l < ļ & L < Ļ & n < ņ & N < Ņ & s < š & S < Š & u < ū & U < Ū & z < ž & Z < Ž'
);
select * from (
select 'bā' as name
union select 'āa'
union select 'ac'
union select 'Āb'
union select 'Ā'
) t
order by name COLLATE latuvian_custom;
name
══════
ac
Ā
Āb
āa
bā
(5 rows)
这些规则在无重音字符和重音字符之间引入了主要级别差异 ()。<
评论
对@Laurenz的伟大答案的一个小补充:为了达到问题中指定的预期结果,需要在初级阶段考虑口音,但大小写不应该。演示:ac Ā āa Āb bā
CREATE COLLATION latvian_custom (PROVIDER=icu,LOCALE='lv',
RULES='&a<Ā=ā &c<Č=č &e<Ē=ē &g<Ģ=ģ &i<Ī=ī &k<Ķ=ķ
&l<Ļ=ļ &n<Ņ=ņ &s<Š=š &u<Ū=ū &z<Ž=ž'
);
SELECT string_agg(sample, E'\t' ORDER BY sample COLLATE "latvian_custom")
FROM (VALUES ('bā'),('āa'),('ac'),('Āb'),('Ā')) AS _(sample);
string_agg |
---|
ac Ā āa Āb bā |
在那个阶段,所有非重音字符都已经等于它们的大写变体,因此将相等的重音对锚定在任一字符后面就足够了(例如 或 )。每个重音字符的两个大小写变体都需要定位为相等 - 作为加法,它们是独立处理的,所以如果你只这样做,它就不起作用了。&A<Ā=ā
&a<Ā=ā
&a<ā &c<č...&z<ž
collation_name | sorted_samples |
---|---|
预期 | ac Ā āa Āb bā (OP的例子) |
违约 | ac bā Ā Āb āa |
latUvian_custom | ac Ā Āb āa bā |
latvian_custom | ac Ā āa Āb bā (唯一比赛) |
latvian_lower_first | Ā āa Āb ac bā |
latvian_lower_first_custom | ac Ā Āb āa bā |
latvian_upper_first | Ā āa Āb ac bā |
latvian_upper_first_custom | ac Ā Āb āa bā |
lv-LV-x-icu | Ā āa Āb ac bā |
LV-X-ICU | Ā āa Āb ac bā |
Unicode的 | Ā āa Āb ac bā |
评论