Закажите строку varchar как числовую - PullRequest
39 голосов
/ 14 декабря 2011

Можно ли упорядочить строки результатов по столбцу varchar, приведенному к integer в Postgres 8.3?

Ответы [ 2 ]

96 голосов
/ 14 декабря 2011

Это абсолютно возможно.

ORDER BY varchar_column::int

Убедитесь, что в столбце varchar указаны допустимые целочисленные литералы, иначе вы получите исключение. (Начальные и конечные пробелы в порядке - они будут обрезаны автоматически.)

Если это так, то почему бы не преобразовать столбец в integer для начала? Меньше, быстрее, чище, проще.

Как избежать исключений?

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

ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
  • Выражение regexp_replace() эффективно удаляет все нецифровые символы, поэтому остаются только цифры или пустая строка. (См. Ниже.)

  • \D - сокращение для класса символов [^[:digit:]], означающее все нецифровые символы ([^0-9]).
    В старых версиях Postgres с устаревшей настройкой standard_conforming_strings = off необходимо использовать синтаксис escape-строки Posix E'\\D', чтобы избежать обратной косой черты \. Это было по умолчанию в Postgres 8.3, поэтому вам понадобится это для вашей устаревшей версии.

  • 4-й параметр g предназначен для «глобально» , инструктируя замену всех вхождений, а не только первого.

  • Вы можете хотите разрешить начальную черту (-) для отрицательных чисел.

  • Если строка не имеет цифр вообще, результатом является пустая строка, которая недопустима для приведения к integer. Преобразуйте пустые строки в NULL с помощью NULLIF. (Вы можете рассмотреть 0 вместо этого.)

Результат гарантированно будет действительным. Эта процедура предназначена для приведения к integer, как указано в основной части вопроса, не для numeric, как упоминается в заголовке.


Как сделать это быстро?

Одним из способов является индекс для выражения . (Ссылка на ручную версию 8.3.)

CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer));

Затем используйте то же выражение в предложении ORDER BY:

ORDER BY
cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer)

Проверьте с помощью EXPLAIN ANALYZE, действительно ли используется функциональный индекс.

4 голосов
/ 04 февраля 2017

Также, если вы хотите упорядочить по текстовому столбцу, в котором есть что-то конвертируемое, чтобы плавать, то это делает это:

select * 
from your_table
order by cast(your_text_column as double precision) desc;
...