PostgreSQL ORDER BY问题 - 自然排序

Mit*_*ran 14 sql postgresql types natural-sort sql-order-by

ORDER BY在下表中遇到了Postgres 问题:

em_code  name
EM001    AAA
EM999    BBB
EM1000   CCC
Run Code Online (Sandbox Code Playgroud)

要向表中插入新记录,

  1. 我选择了最后一条记录 SELECT * FROM employees ORDER BY em_code DESC
  2. 从em_code中删除使用reg exp和存储的字母 ec_alpha
  3. 将重映射部分转换为整数 ec_num
  4. 增加一个 ec_num++
  5. 垫有足够zeors和前缀ec_alpha再次

em_code到达EM1000,上述算法失败.

第一步将返回EM999而不是EM1000,它将再次生成EM1000为新的em_code,打破了唯一键约束.

知道如何选择EM1000吗?

Bou*_*egh 31

从 Postgres 9.6 开始,可以指定一个排序规则来自然地对带有数字的列进行排序。

\n

https://www.postgresql.org/docs/10/collat​​ion.html

\n
-- First create a collation with numeric sorting\nCREATE COLLATION numeric (provider = icu, locale = \'en@colNumeric=yes\');\n\n-- Alter table to use the collation\nALTER TABLE "employees" ALTER COLUMN "em_code" type TEXT COLLATE numeric;\n
Run Code Online (Sandbox Code Playgroud)\n

现在只需像其他方式一样查询即可。

\n

SELECT * FROM employees ORDER BY em_code

\n

在我的数据上,我按以下顺序得到结果(请注意,它还会对外来数字进行排序):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n
价值
0
0001
001
1
06
6
13
\xdb\xb1\xdb\xb3
14
\n

  • 这绝对应该得到更多的支持。可以说是最干净、最惯用的方法。 (2认同)

Erw*_*ter 9

原因是字符串按字母顺序排序(而不是像你想要的那样数字排序)和1之前的排序.你可以像这样解决它:

SELECT * FROM employees ORDER BY substring(em_code, 3)::int DESC
Run Code Online (Sandbox Code Playgroud)

em_code如果可以的话,从你的中删除多余的"EM"会更有效- 并保存一个整数开头.


评论中的问题的补充答案

要从字符串中删除任何和所有非数字:

SELECT regexp_replace(em_code, E'\\D','','g')
FROM employees
Run Code Online (Sandbox Code Playgroud)

\D是"非数字" 的正则表达式类 - 简写.
'g'第四个参数是"全局"开关,用于将替换应用于字符串中的每个匹配项,而不仅仅是第一个.

所以我用空字符串替换每个非数字,只从字符串中提取数字.


Jon*_*han 8

您可以采用的一种方法是为此创建一个naturalsort函数。这是一个由Postgres传奇人物RhodiumToad编写的示例。

create or replace function naturalsort(text)
    returns bytea language sql immutable strict as $f$
    select string_agg(convert_to(coalesce(r[2], length(length(r[1])::text) || length(r[1])::text || r[1]), 'SQL_ASCII'),'\x00')
    from regexp_matches($1, '0*([0-9]+)|([^0-9]+)', 'g') r;
$f$;
Run Code Online (Sandbox Code Playgroud)

资料来源:http : //www.rhodiumtoad.org.uk/junk/naturalsort.sql

要使用它,只需按以下顺序调用函数:

SELECT * FROM employees ORDER BY naturalsort(em_code) DESC
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以仅使用这一行“ORDER BY length(substring(em_code FROM '[0-9]+')), em_code”


sag*_*eta 5

这总是在问题和我自己的发展中出现,我终于厌倦了棘手的方法。我终于分解并实现为PostgreSQL扩展:

https://github.com/Bjond/pg_natural_sort_order

MIT许可证免费使用。

基本上,它只是规范化字符串中的数字(零个前置数字),以便您可以为全速排序自然创建索引列。自述文件进行了解释。

好处是您可以让触发器来完成工作,而不是应用程序代码。它将在PostgreSQL服务器上以机器速度进行计算,并且添加列的迁移变得简单而快速。