将 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 字符串排序为数字的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server - 将 varchar 转换为另一个排序规则(代码页)以修复字符编码