oracle 中文数字混合 排序 字段book_no需要先按照中文分组后按照后面的数字编号排序,也就是一组一排序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 中文数字混合 排序 字段book_no需要先按照中文分组后按照后面的数字编号排序,也就是一组一排序相关的知识,希望对你有一定的参考价值。

主要是还需要按照数字进行排序,如图所示:哈电集团[2007]2号应在第一位,其次是8号........

由于前期存储数据时没有规划好造成排序非常复杂,使得排序性能会很差
基本的处理思路如下:
1。对"]"之前的部分作为一虚拟字段作排序
2。对"]"之后,"号"之前部分(即数值部分)提取出来转换成NUMBER数据类型作排序
with data as (
select 'CCC[2007]111号' as book_no from dual union all
select 'CCC[2007]112号' as book_no from dual union all
select 'CCC[2007]22号' as book_no from dual union all
select 'CCC[2007]56号' as book_no from dual union all
select 'AAAAAAA[2007]121号' as book_no from dual union all
select 'AAAAAAA[2007]122号' as book_no from dual union all
select 'AAAAAAA[2007]2号' as book_no from dual union all
select 'AAAAAAA[2007]33号' as book_no from dual union all
select 'BBBB[2007]111号' as book_no from dual union all
select 'BBBB[2007]112号' as book_no from dual union all
select 'BBBB[2007]3号' as book_no from dual union all
select 'BBBB[2007]56号' as book_no from dual
)
select book_no
from data
order by substr (book_no, 1, instr (book_no, ']')),
to_number (
replace (regexp_substr (book_no, '\]([[:digit:]]+)'), ']', ''))

BOOK_NO
------------------
AAAAAAA[2007]2号
AAAAAAA[2007]33号
AAAAAAA[2007]121号
AAAAAAA[2007]122号
BBBB[2007]3号
BBBB[2007]56号
BBBB[2007]111号
BBBB[2007]112号
CCC[2007]22号
CCC[2007]56号
CCC[2007]111号
CCC[2007]112号
参考技术A 字符型的排序会逐个比较,所以出现上述排序情况,在相同位置的字符比较排序的,所以1**在前面,之后是2**类推。想达到理想要求,比较困难的。如果此数据录入顺序和想要显示的顺序一致,可以用rowid来排序试试 参考技术B select book_no from tab_name order by book_no asc;

Postgresql 对混合字母数字数据进行排序

【中文标题】Postgresql 对混合字母数字数据进行排序【英文标题】:Postgresql sorting mixed alphanumeric data 【发布时间】:2011-08-10 22:21:31 【问题描述】:

运行此查询:

select name from folders order by name

返回这些结果:

alphanumeric
a test
test 20
test 19
test 1
test 10

但我期待:

a test
alphanumeric
test 1
test 10
test 19
test 20

这里有什么问题?

【问题讨论】:

看起来很奇怪:'test 20' < 'test 19'。通过检查 SHOW lc_collate; 你有什么 LC_COLLATE ?我有en_US.UTF-8,它使用ORDER BY name ASC 返回完全想要的输出。 我也得到了同样的结果。我刚刚做了select 'alphanumeric' < 'a test' 并得到了f 为了记录,我发布了一个答案,指向您手动输入进行整理。它被认为不够可爱,所以我删除了它。但我认为你应该从那里开始。 @andrew cooke:我没有投反对票,这很好,排序规则负责排序,但是仅支持 每列排序规则,这在此处可能很有用从 Postgres 9.1 开始。 您好,感谢您的 cmets... SHOW lc_collat​​e;正在返回 es_SV.UTF-8(我住在萨尔瓦多) 【参考方案1】:

您可以简单地将 name 列转换为 bytea 数据类型,从而允许与排序无关的排序:

SELECT name
FROM folders
ORDER BY name::bytea;

结果:

     name     
--------------
 a test
 alphanumeric
 test 1
 test 10
 test 19
 test 20
(6 rows)

【讨论】:

大师!这个答案绝对是我过去 2 小时一直在寻找的答案!来自Mysql,当没有数字时将varchars转换为整数时不会出错...... 这修复了TRIM 无法解决的前导空格排序问题。 小心,因为它仍然是字母数字(意思是“3”将出现在“20”之后)【参考方案2】:

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

test 1
test 10
test 2
test 20

这个解决方案对我有用(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

【讨论】:

【参考方案3】:
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";

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

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

1 10 2 21 一个 A1 A11 A5 B B2 B22 B3 M 1 M 11 M 2

查询结果,修改后:

1 2 10 21 一个 A1 A5 A11 B B2 B3 B22 M 1 M 2 M 11

【讨论】:

这是一个很好的答案 嗨,Deepak,如何在 sqlite/websql 中复制它? 这是我们系统的绝佳解决方案。干得好迪帕克【参考方案4】:

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

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

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

在我的测试中运行良好。

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

【讨论】:

为什么投反对票?它有效,并解决了这种情况。这不是最佳 解决方案,但它不涉及更改数据库结构。如果您觉得需要投反对票,请至少发表评论。 -1 表示无法解决真正问题的奇怪的 kluge。 (带有多个空格和/或数字的字符串呢?)请参阅上面关于排序规则的 cmets。 我不会说这是一个奇怪的组合。它增加了对尾随数字进行数字排序的能力,而不需要特定版本的 PG。它很好地处理 尾随 数字,因此适用于按顺序编号的文件夹。它处理多个空格,因为它只是检查以确保在尾随数字之前至少有一个空格。如果你尝试过,你会发现它有效,而不是假设。 不适用于诸如“H1C11”之类的文本,因为它为第一个数字排序,而不是尾数【参考方案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;

所以这个:

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

【讨论】:

【参考方案6】:

上面 Vlk 的回答对我帮助很大,但它仅按数字部分对项目进行排序,在我的情况下排在第二位。我的数据就像(办公桌 1、办公桌 2、办公桌 3 ...)一个字符串部分、一个空格和一个数字部分。 A Vlk 的答案中的语法返回了按数字排序的数据,这是上面唯一的答案。但是,当字符串部分不同时(例如,3 号桌、4 号桌、1 号桌、5 号桌...),1 号桌将首先从 2 号桌开始。我使用以下语法解决了这个问题:

    ...order by SUBSTRING(name,'\\w+'), SUBSTRINGname FROM '([0-9]+)')::BIGINT ASC;

【讨论】:

【参考方案7】:

Tor 的最后一条 SQL 对我有用。但是,如果您从 php 调用此代码,则需要添加额外的斜杠。

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;

【讨论】:

以上是关于oracle 中文数字混合 排序 字段book_no需要先按照中文分组后按照后面的数字编号排序,也就是一组一排序的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL数据库字母数字混合字段排序问题

如何用SQL语句,在数字加中文的混合数据中提取出中文

oracle,如何添加排序编号字段

如何使用 Oracle SQL 查询先按数字排序?

javascript 自己实现数字字母和中文的混合排序方法 by FungLeo

oracle 表中如何对按含有字母和数字的编号来进行排序