将varchar字符串排序为数字

Jau*_*ika 41 postgresql indexing types integer casting

是否可以通过Postgres 8.3中的varchar列强制对结果行进行排序integer

Erw*_*ter 100

这绝对是可能的.

ORDER BY varchar_column::int
Run Code Online (Sandbox Code Playgroud)

确保列中包含有效的整数文字,varchar否则会出现异常.(前导和尾随空白区域正常 - 它将自动修剪.)

如果是这种情况,那么为什么不将列转换integer为开头?更小,更快,更清洁,更简单.

如何避免异常?

要在演员表之前删除非数字字符,从而避免可能的例外情况:

ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
Run Code Online (Sandbox Code Playgroud)
  • regexp_replace()表达式有效地删除了所有非数字,因此只保留数字或空字符串.(见下文.)

  • \D是字符类的简写[^[:digit:]],表示所有非数字([^0-9]).
    在具有过时设置的旧Postgres版本中standard_conforming_strings = off,您必须使用Posix转义字符串语法E'\\D'来转义反斜杠\.这是Postgres 8.3中的默认值,因此您需要使用过时的版本.

  • 第四个参数g"全局",指示替换所有出现,而不仅仅是第一个.

  • 可能希望允许前导破折号(-)表示负数.

  • 如果字符串根本没有数字,则结果是一个空字符串,对于强制转换为无效integer.转换空字符串来NULLNULLIF.(你可以考虑0改为.)

结果保证有效.此过程适用integer于问题正文中所要求的演员表,而不是numeric标题所提及的.


如何让它快?

一种方法是表达式索引.(链接到手册版本8.3.)

CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
Run Code Online (Sandbox Code Playgroud)

然后在ORDER BY子句中使用相同的表达式:

ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Run Code Online (Sandbox Code Playgroud)

测试EXPLAIN ANALYZE功能索引是否实际使用.

  • @Jauzsika:绝对比普通演员慢,但不是那么多.你必须计算价值的事实是这里的主要减速.如果要快速,请将表中的列转换为整数,或者添加包含预先计算的整数的冗余列.然后你可以索引列,这将使**更快*(前提是查询很简单,索引可以用于排序).**或**使用表达式的索引.我修改了我的答案. (3认同)

Eri*_*ski 6

另外,如果您想按具有可转换为浮动的内容的文本列进行排序,则可以这样做:

select * 
from your_table
order by cast(your_text_column as double precision) desc;
Run Code Online (Sandbox Code Playgroud)