PostgreSQL中的自定义排序(order by),与locale无关

时间:2010-12-07 21:23:42

标签: sql database postgresql

假设我有一个包含两列的简单表:id(int)和name(varchar)。在此表中,我存储了一些波兰语的名称,例如:

 1 | sępoleński
 2 | świecki
 3 | toruński
 4 | Włocławek

现在,假设我想按名称对结果进行排序:

SELECT * FROM table ORDER BY name;

如果我有C语言环境,我会得到:

 4 | Włocławek
 1 | sępoleński
 3 | toruński
 2 | świecki

这是错误的,因为“ś”应该在“s”之后和“t”之前。如果我使用波兰语语言环境(pl_PL.UTF-8),我会得到:

 1 | sępoleński
 2 | świecki
 3 | toruński
 4 | Włocławek

这也不是我想要的,因为我希望以大写字母开头的名字首先就像在C语言环境中一样,如下所示:

 4 | Włocławek
 1 | sępoleński
 2 | świecki
 3 | toruński

我该怎么做?

2 个答案:

答案 0 :(得分:2)

如果您想要自定义排序,则必须定义一些以某种方式修改值的函数,以便修改后的值的自然顺序符合您的要求。

例如,您可以附加一些字符或字符串,其值以大写字母开头:

 CREATE OR REPLACE FUNCTION mysort(text) returns text IMMUTABLE as $$
   SELECT CASE WHEN substring($1 from 1 for 1) =
   upper( substring($1 from 1 for 1))  then 'AAAA' || $1 else $1 END
   ;
   $$  LANGUAGE SQL;

然后

SELECT * FROM table ORDER BY mysort(name);

这不是万无一失(当然,你可能想把'AAA'换成更合适的东西)并且会伤害性能。

答案 1 :(得分:1)

如果您希望它有效,则需要创建另一个“自然”正确排序的列(例如,甚至在C语言环境中),并将其用作排序标准。为此,您应该使用strxfrm C库函数的方法。作为您的方法的直接strxfrm表,用两个ASCII字母替换每个字母:'s'将变为's0','ś'将变为's1'。然后'świecki'变为's1w0i0e0c0k0i0',常规ASCII排序将对其进行正确排序。

如果您不想创建单独的列,可以尝试在where子句中使用函数:

SELECT * FROM table ORDER BY strxfrm(name);

这里,strxfrm需要用适当的功能替换。你自己写一个,或者你使用标准的translate函数(虽然这不支持用其中两个替换一个字符,所以你需要一些更复杂的转换)。