Postgresql排序混合的字母数字数据

el_*_*ick 12 sorting postgresql alphanumeric

运行此查询:

select name from folders order by name
Run Code Online (Sandbox Code Playgroud)

返回这些结果:

alphanumeric
a test
test 20
test 19
test 1
test 10
Run Code Online (Sandbox Code Playgroud)

但我预计:

a test
alphanumeric
test 1
test 10
test 19
test 20
Run Code Online (Sandbox Code Playgroud)

这有什么不对?

Grz*_*ski 21

您可以简单地将name列转换bytea为允许整理不可知顺序的数据类型:

SELECT name
FROM folders
ORDER BY name::bytea;
Run Code Online (Sandbox Code Playgroud)

结果:

     name     
--------------
 a test
 alphanumeric
 test 1
 test 10
 test 19
 test 20
(6 rows)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,因为它仍然是字母数字(表示“ 3”将在“ 20”之后) (4认同)
  • 掌握!这个答案绝对是我过去 2 小时一直在寻找的答案!来自 Mysql,当没有数字时,将 varchars 转换为整数时不会出错.... (2认同)

小智 8

所有这些方法都按字母顺序对我的选择进行了排序:

test 1
test 10
test 2
test 20
Run Code Online (Sandbox Code Playgroud)

这个解决方案对我有用(lc_collat​​e:'ru_RU.UTF8'):

SELECT name
FROM folders
ORDER BY SUBSTRING(name FROM '([0-9]+)')::BIGINT ASC, name;

test 1
test 2
test 10
test 20
Run Code Online (Sandbox Code Playgroud)


Dee*_*dey 8

select * from "public"."directory" where "directoryId" = 17888 order by
COALESCE(SUBSTRING("name" FROM '^(\d+)')::INTEGER, 99999999),
SUBSTRING("name" FROM '[a-zA-z_-]+'),
COALESCE(SUBSTRING("name" FROM '(\d+)$')::INTEGER, 0),
"name";
Run Code Online (Sandbox Code Playgroud)

注意:根据需要转义正则表达式,在某些语言中,您必须再添加一个“\”。

在我的 Postgres 数据库中,当我使用按名称查询的简单顺序时,名称列包含以下内容:

  • 1
  • 10
  • 2
  • 21
  • 一种
  • A1
  • A11
  • A5
  • B2
  • B22
  • B3
  • 米 1
  • 米 11
  • 米 2

查询结果,修改后:

  • 1
  • 2
  • 10
  • 21
  • 一种
  • A1
  • A5
  • A11
  • B2
  • B3
  • B22
  • 米 1
  • 米 2
  • 米 11


Ove*_*ous 7

如果有尾随数字,您可以通过拆分文本来手动排序,如下所示:

SELECT * FROM sort_test
ORDER BY SUBSTRING(text FROM '^(.*?)( \\d+)?$'),
         COALESCE(SUBSTRING(text FROM ' (\\d+)$')::INTEGER, 0);
Run Code Online (Sandbox Code Playgroud)

这将对列文本进行排序,首先是所有字符(可选地,不包括结尾空格,后跟数字),然后是那些可选数字。

在我的测试中表现良好。

更新修复了具有简单合并(duh)的仅字符串排序。


小智 5

OverZealous 答案对我有帮助,但如果数据库中的字符串以数字开头,后跟附加字符,则不起作用。

以下对我有用:

SELECT name
FROM folders
ORDER BY
COALESCE(SUBSTRING(name FROM '^(\\d+)')::INTEGER, 99999999),
SUBSTRING(name FROM '^\\d* *(.*?)( \\d+)?$'),
COALESCE(SUBSTRING(name FROM ' (\\d+)$')::INTEGER, 0),
name;
Run Code Online (Sandbox Code Playgroud)

所以这个:

  1. 提取字符串中的第一个数字,或使用 99999999。
  2. 提取可能的第一个数字后面的字符串。
  3. 提取尾随数字,或使用 0。