Пользовательская сортировка (упорядочение по) в PostgreSQL, независимо от локали - PullRequest
1 голос
/ 08 декабря 2010

Допустим, у меня есть простая таблица с двумя столбцами: 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 ]

2 голосов
/ 08 декабря 2010

Если вы хотите пользовательскую сортировку, вы должны определить некоторую функцию, которая каким-то образом изменяет ваши значения так, чтобы естественный порядок измененных значений соответствовал вашим требованиям.

Например, вы можете добавить какой-либо символ или строку, если значение начинается с заглавной буквы:

 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 голос
/ 08 декабря 2010

Если вы хотите, чтобы он был эффективным, вам нужно создать еще один столбец, который "естественно" сортирует правильно (например, даже в локали C), и использовать его в качестве критерия сортировки. Для этого вам следует использовать подход библиотечной функции strxfrm C. В качестве простой таблицы strxfrm для вашего подхода замените каждую букву двумя буквами ASCII: «s» станет «s0», а «ś» станет «s1». Тогда 'świecki' становится 's1w0i0e0c0k0i0', и обычная сортировка ASCII сортирует его правильно.

Если вы не хотите создавать отдельный столбец, вы можете попробовать использовать функцию в предложении where:

SELECT * FROM table ORDER BY strxfrm(name);

Здесь strxfrm необходимо заменить соответствующей функцией. Либо вы пишете один самостоятельно, либо используете стандартную функцию translate (хотя она не поддерживает замену символа двумя из них, поэтому вам потребуется более сложное преобразование).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...