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_collate;正在返回 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_collate: '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需要先按照中文分组后按照后面的数字编号排序,也就是一组一排序的主要内容,如果未能解决你的问题,请参考以下文章