将 varchar 字符串排序为数字

Posted

技术标签:

【中文标题】将 varchar 字符串排序为数字【英文标题】:Order varchar string as numeric 【发布时间】:2012-01-20 02:39:43 【问题描述】:

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

【问题讨论】:

【参考方案1】:

绝对有可能。

ORDER BY varchar_column::int

确保每个条目的varchar 列中都有有效的整数文字,否则会出现异常invalid input syntax for integer: ...。 (前导和尾随空格是可以的 - 它将被自动修剪。)

如果是这样,那么为什么不将列转换为 integer 开始呢?更小、更快、更清洁、更简单。

如何避免异常?

在强制转换之前删除非数字字符,从而避免可能的异常:

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

regexp_replace() 表达式有效地删除了所有非数字,因此只保留数字或空字符串。 (见下文。)

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

第 4 个参数 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_column, '\D', '', 'g'), '') AS integer));

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

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

EXPLAIN ANALYZE测试函数索引是否真的被使用了。

【讨论】:

有什么办法可以避免这种异常? :) @Jauzsika:您必须首先定义非整数值的结果。最后排序?或者在演员表之前删除任何非数字字符? 感谢例外部分。那个正则表达式看起来很慢,对吗? @Jauzsika:肯定比普通演员要慢,但没那么慢。您必须计算值的事实是这里的主要减速。如果您想要快速,请将表中的列转换为整数,或者添加一个包含预先计算的整数的冗余列。然后,您可以为该列建立索引,这将使其快很多(前提是查询很简单并且可以使用索引进行排序)。 在表达式上使用索引。我修改了答案。 感谢您精疲力竭的培训 :))。【参考方案2】:

此外,如果您想按可转换为浮动的文本列进行排序,那么可以这样做:

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

【讨论】:

以上是关于将 varchar 字符串排序为数字的主要内容,如果未能解决你的问题,请参考以下文章

mysql 字符串按照数字类型排序

MySQL 数字字符串按照数字排序

SQL Server - 将 varchar 转换为另一个排序规则(代码页)以修复字符编码

Mysql数据库按照varchar字符串类型排序和按照int整型类型排序的区别和注意点及解决方案

sql数字字符串排序

Mysql之 order by 排序