Неправильная сортировка/сопоставление/порядок с пробелами в Postgresql 9.4

Я использую Postgresql 9.4.5. Когда я иду в psql и запускаю \l, я получаю

Encoding is UTF8
Collate is en_US.UTF-8 
cCtype is en_US.UTF-8

У меня есть таблица products со столбцом name со следующими именами:

T-700A Grouped
T-700 AGrouped
T-700A Halved
T-700 Whole

Когда я выполняю следующий SQL в pql

SELECT name FROM products WHERE name LIKE '%T-700%' ORDER By name ASC;

Я получаю следующий вывод

T-700A Grouped
T-700 AGrouped
T-700A Halved
T-700 Whole

Такая сортировка не выглядит естественной. я ожидал получить

T-700 AGrouped
T-700 Whole
T-700A Grouped
T-700A Halved

Не похоже, что Postgres обрабатывает пробелы так, как я ожидал. Может ли кто-нибудь объяснить, что происходит, и предложить способ исправить это?


person CodeSmith    schedule 30.12.2015    source источник
comment
Может ли это быть вам полезным?   -  person Tim Biegeleisen    schedule 31.12.2015
comment
Ага, похоже похожая проблема. Однако они не решают проблему в глобальном масштабе. Я хотел бы иметь возможность настроить базу данных таким образом, чтобы все текстовые столбцы по умолчанию вели себя одинаково.   -  person CodeSmith    schedule 31.12.2015
comment
См. Порядок символов UTF-8 в Postgres.   -  person klin    schedule 31.12.2015


Ответы (1)


На Unix/Linux SE дружелюбный эксперт объяснил, что вы видите правильный способ сортировки Unicode. По сути, стандарт пытается отсортировать:

di Silva Fred                  di Silva Fred
di Silva John                  diSilva Fred
diSilva Fred                   disílva Fred
diSilva John         ->        di Silva John
disílva Fred                   diSilva John
disílva John                   disílva John

Итак, если бы пробелы были так же важны, как буквы, сортировка не могла бы разделить различные одинаковые варианты написания Фреда и Джона. Итак, что происходит, так это то, что он сначала сортируется без пробелов. Затем при втором проходе сортируются одинаковые строки без пробелов. (Это упрощение, реальный алгоритм выглядит довольно сложным, присваивая пробелам, диакритическим знакам и непечатаемым символам различные уровни приоритета.)

Вы можете обойти сопоставление Unicode, установив:

export LC_ALL=C

Или в Postgres путем приведения к массиву байтов для сортировки:

order by name::bytea

Или (из Kiln answer), указав сопоставление C:

order by name collate "C"

Или изменив параметры сортировки по умолчанию для столбца:

alter table products alter column name type text collate "C";
person Andomar    schedule 30.12.2015
comment
Я задал вопрос на linux/unix stackexchange... возможно, гуру Unix знает ответ :) - person Andomar; 31.12.2015
comment
Это просто спасло меня, какие пару часов это было - person jdcookie; 23.02.2017
comment
Данные решения работают для английского языка, но что, если мне все еще нужно сортировать по правилам, зависящим от локали? Мне нужна сортировка Юникода по словам. В отпуск должен приехать раньше Один. - person Tomáš Cerha; 14.02.2020