Oracle SQL 对版本号进行排序
Oracle SQL to Sort Version Numbers
在 Oracle 中,仅使用 ORDER BY
不会对版本号进行排序。
我的 Version_Number
字段被声明为 VARCHAR
,我无法更改它。
例如:以下版本:
1.20
1.9
1.18
1.13
1.5
1.11
2.0
1.8
1.3
1.2
1.1
1.0
1.10
应该排序为
2.0
1.20
1.18
1.13
1.11
1.10
1.9
1.8
1.5
1.3
1.2
1.1
1.0
我研究了几个 post,但其中 none 似乎确实符合我的目的,或者答案是针对 SQL 服务器等而不是 Oracle。我遇到了这个特别的 sql,它看起来很有效。
select version_number from mytable
order by lpad(version_number, 4) desc;
以这种方式对版本进行排序:
1.20
1.18
1.13
1.11
1.10
2.0
1.9
1.8
1.5
1.3
1.2
1.1
1.0
我相信这个 sql 声明适用于 SQL Server
:
select version_number from mytable
order by cast ('/' + replace(version_number , '.', '/') + '/' as hierarchyid) desc;
但是,这不适用于 Oracle。 Oracle 中是否有替代 hierarchyid 的方法?
有谁能想出一个 SQL 来准确地对这些版本进行排序吗?
我已经看到下面提到的 posts(附加链接)。所以请不要告诉我这个 post 是重复的。
SQL sort by version "number", a string of varying length
How Can I Sort A 'Version Number' Column Generically Using a SQL Server Query
Version number sorting in Sql Server
mysql sorting of version numbers
还有更多。
这是一种方法。先按.
前的数字排序,再按.
后的数字排序
select version_number
from mytable
order by substr(version_number, 1, instr(version_number,'.')-1) desc
,length(substr(version_number, instr(version_number,'.')+1)) desc
,substr(version_number, instr(version_number,'.')+1) desc
正如 Joel Coehoorn 的建议 here、"refactor version number storage so that each section has it's own column: MajorVersion, MinorVersion, Revision, Build"。
我正在重新发布,因为我发现这个非常有用!
为了扩展,我一直在寻找 MAX
版本号,最后根据 Joel 的建议使用了这个脚本。
-- GET MAX VERSION NUMBER
SELECT
REPLACE(vnum, ' ', '') AS versionum
FROM
(SELECT
MAX(LPAD(major, 4) || '.' || LPAD(minor, 4) || '.' || LPAD(revision, 4)) AS vnum
FROM
my_table
ORDER BY
major
, minor
, revision
) tbl1
此 SQL 支持您的输入数据以及任何包含的修订版或内部版本数字。
with
inputs as (select '1.20' as version_number from dual union all
select '1.9' as version_number from dual union all
select '1.18' as version_number from dual union all
select '1.13' as version_number from dual union all
select '1.5' as version_number from dual union all
select '1.11' as version_number from dual union all
select '2.0' as version_number from dual union all
select '1.8' as version_number from dual union all
select '1.3' as version_number from dual union all
select '1.2' as version_number from dual union all
select '1.1' as version_number from dual union all
select '1.0' as version_number from dual union all
select '1.10' as version_number from dual union all
select ' 3.1 ' as version_number from dual union all
select '3.1.1000' as version_number from dual union all
select '3.1.1' as version_number from dual union all
select '3.1.100' as version_number from dual union all
select '3.1.2.1000' as version_number from dual union all
select '3.1.2.1' as version_number from dual union all
select '3.1.2.100 ' as version_number from dual)
,versions as (select trim(version_number) as version_number,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 1)),5,'0'),'00000') AS Major,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 2)),5,'0'),'00000') AS Minor,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 3)),5,'0'),'00000') AS Revision,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 4)),5,'0'),'00000') AS Build
from inputs
ORDER BY Major desc, Minor desc, Revision desc, Build desc)
--select * from versions;
select version_number from versions;
删除 -- 以查看中间结果。
对于 OP,将 "inputs as (select ... from dual)" 替换为:
inputs as (select version_number from mytable)
在 Oracle 中,仅使用 ORDER BY
不会对版本号进行排序。
我的 Version_Number
字段被声明为 VARCHAR
,我无法更改它。
例如:以下版本:
1.20
1.9
1.18
1.13
1.5
1.11
2.0
1.8
1.3
1.2
1.1
1.0
1.10
应该排序为
2.0
1.20
1.18
1.13
1.11
1.10
1.9
1.8
1.5
1.3
1.2
1.1
1.0
我研究了几个 post,但其中 none 似乎确实符合我的目的,或者答案是针对 SQL 服务器等而不是 Oracle。我遇到了这个特别的 sql,它看起来很有效。
select version_number from mytable
order by lpad(version_number, 4) desc;
以这种方式对版本进行排序:
1.20
1.18
1.13
1.11
1.10
2.0
1.9
1.8
1.5
1.3
1.2
1.1
1.0
我相信这个 sql 声明适用于 SQL Server
:
select version_number from mytable
order by cast ('/' + replace(version_number , '.', '/') + '/' as hierarchyid) desc;
但是,这不适用于 Oracle。 Oracle 中是否有替代 hierarchyid 的方法?
有谁能想出一个 SQL 来准确地对这些版本进行排序吗?
我已经看到下面提到的 posts(附加链接)。所以请不要告诉我这个 post 是重复的。
SQL sort by version "number", a string of varying length
How Can I Sort A 'Version Number' Column Generically Using a SQL Server Query
Version number sorting in Sql Server
mysql sorting of version numbers
还有更多。
这是一种方法。先按.
前的数字排序,再按.
select version_number
from mytable
order by substr(version_number, 1, instr(version_number,'.')-1) desc
,length(substr(version_number, instr(version_number,'.')+1)) desc
,substr(version_number, instr(version_number,'.')+1) desc
正如 Joel Coehoorn 的建议 here、"refactor version number storage so that each section has it's own column: MajorVersion, MinorVersion, Revision, Build"。
我正在重新发布,因为我发现这个非常有用!
为了扩展,我一直在寻找 MAX
版本号,最后根据 Joel 的建议使用了这个脚本。
-- GET MAX VERSION NUMBER
SELECT
REPLACE(vnum, ' ', '') AS versionum
FROM
(SELECT
MAX(LPAD(major, 4) || '.' || LPAD(minor, 4) || '.' || LPAD(revision, 4)) AS vnum
FROM
my_table
ORDER BY
major
, minor
, revision
) tbl1
此 SQL 支持您的输入数据以及任何包含的修订版或内部版本数字。
with
inputs as (select '1.20' as version_number from dual union all
select '1.9' as version_number from dual union all
select '1.18' as version_number from dual union all
select '1.13' as version_number from dual union all
select '1.5' as version_number from dual union all
select '1.11' as version_number from dual union all
select '2.0' as version_number from dual union all
select '1.8' as version_number from dual union all
select '1.3' as version_number from dual union all
select '1.2' as version_number from dual union all
select '1.1' as version_number from dual union all
select '1.0' as version_number from dual union all
select '1.10' as version_number from dual union all
select ' 3.1 ' as version_number from dual union all
select '3.1.1000' as version_number from dual union all
select '3.1.1' as version_number from dual union all
select '3.1.100' as version_number from dual union all
select '3.1.2.1000' as version_number from dual union all
select '3.1.2.1' as version_number from dual union all
select '3.1.2.100 ' as version_number from dual)
,versions as (select trim(version_number) as version_number,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 1)),5,'0'),'00000') AS Major,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 2)),5,'0'),'00000') AS Minor,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 3)),5,'0'),'00000') AS Revision,
nvl(LPAD(trim(regexp_substr(version_number, '[^.]+', 1, 4)),5,'0'),'00000') AS Build
from inputs
ORDER BY Major desc, Minor desc, Revision desc, Build desc)
--select * from versions;
select version_number from versions;
删除 -- 以查看中间结果。
对于 OP,将 "inputs as (select ... from dual)" 替换为:
inputs as (select version_number from mytable)