postgresql 将varchar字符串排序为数字

w8f9ii69  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(323)

在Postgres 8.3中,是否可以通过将varchar列转换为integer来对结果行进行排序?

k7fdbhmy

k7fdbhmy1#

完全有可能。

ORDER BY varchar_col::int

字符串
请确保varchar列中的每个条目都有有效的整数文字,否则将出现异常invalid input syntax for integer。前导和尾随白色是可以的-这是自动修剪的。
如果是这样的话,那么为什么不开始将列转换为integer呢?更小、更快、更干净、更简单。

如何避免异常?

Postgres 16或更高版本

如果输入可能不是有效的整数文字,请使用专用函数pg_input_is_valid()进行测试,而不会引发异常:

ORDER BY CASE WHEN pg_input_is_valid(varchar_col, 'integer') THEN varchar_col::int END


SQL CASE在没有ELSE的情况下默认为null-按默认升序排序最后。请参阅:

  • 按列ASC排序,但首先是NULL值?

新的内置功能比手动解决方案更快,更可靠。不同之处还在于它不尝试修复损坏的输入。

Postgres 15岁以上

要在强制转换之前删除非数字字符,从而避免可能的异常,请执行以下操作:

ORDER BY NULLIF(regexp_replace(varchar_col, '\D', '', 'g'), '')::int

  • regexp_replace()表达式有效地删除了所有非数字,因此只保留数字或空字符串。(见下文。)
  • \D是字符类[^[:digit:]]的简写,表示所有非数字([^0-9])。

在旧的Postgres版本中,设置为过时的standard_conforming_strings = off,你必须使用Posix转义字符串语法E'\\D'来转义反斜杠\。这是Postgres 8.3的默认设置,所以你需要为你的过时版本。

  • 第四个参数g用于 “globally”,指示替换 * 所有 * 次,而不仅仅是第一次。
  • 您可能希望允许负数使用前导破折号(-)。
  • 如果字符串根本没有数字,则结果是空字符串,对于转换为integer无效。使用NULLIF将空字符串转换为NULL。(您可以考虑使用0。)

保证结果有效。这个过程是针对问题主体中要求的**integer**的转换,而不是标题中提到的numeric *。

如何快速?

一种方式是index on an expression

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


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

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


使用EXPLAIN ANALYZE测试函数索引是否被实际使用。

tjrkku2a

tjrkku2a2#

另外,如果你想按一个文本列排序,该列有可转换为float的内容,那么这就可以做到:

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

字符串

相关问题