Sql Maven版本订购
我有一个Maven项目表。每个项目都有许多参数和版本号 当我从表中选择时,我应该只得到最高的版本,但是由于maven版本的外观,这很棘手。这是我到目前为止提出的问题:Sql Maven版本订购,sql,regex,postgresql,maven,natural-sort,Sql,Regex,Postgresql,Maven,Natural Sort,我有一个Maven项目表。每个项目都有许多参数和版本号 当我从表中选择时,我应该只得到最高的版本,但是由于maven版本的外观,这很棘手。这是我到目前为止提出的问题: select id, group_id as group, artifact_id as artifact from ( select p.group_id, p.artifact_id, p.id, rank() over (partition by p.group_id, p.a
select id, group_id as group, artifact_id as artifact
from (
select
p.group_id,
p.artifact_id,
p.id,
rank() over (partition by p.group_id, p.artifact_id order by p.version desc)
from projects p
) as ranked
where ranked.rank = 1
这不会给出最高版本,因为该版本不遵循字母数字顺序。要点是一个版本可以是
1.2.3-SNAPSHOT
,其中1
(主要)、2
(次要)、3
(增量)是数字,应该按数字顺序排列,SNAPSHOT
(限定符)是字符串。如果版本不遵循此格式,则应将其视为字符串
这在PostgreSQL中可行吗?解析字符串。比如:
SELECT version
,substring(version, '^(\d+)')::int AS major
,substring(version, '^\d+\.(\d+)')::int AS minor
,substring(version, '^\d+\.\d+\.(\d+)')::int AS incremental
,substring(version, '-(.+)$') AS qualifier
FROM (
VALUES
('1.2.3-SNAPSHOT')
, ('2-FOO')
, ('2-BAR')
, ('2.1-BAR')
, ('13.5.6-SNAPSHOT')
, ('13.11.11-SNAPSHOT')
) x(version)
ORDER BY major NULLS LAST
, minor NULLS FIRST
, incremental NULLS FIRST
, qualifier NULLS FIRST;
。。用于解析。子字符串(版本“^(\d+)”
。。字符串的开头^
。。捕获括号()
。。数字的类速记\d
。。强制转换为整数以像数字一样排序子字符串(版本“^(\d+)::int
- 。。没有数字的版本最后一个(我的假设)
<代码>2位于先将小空值
2.1
是中的默认值,可以省略NULLS LAST
regexp\u matches()
是一个功能强大的工具,但您需要对正则表达式有基本的了解。如果有疑问,进行测试。特别注意:
- 不添加
开关李>g
- 注意捕获
和非捕获括号()
之间的区别(:?)
。。非匹配项在数组中列为空字符串。需要先转换为NULLIF(第[1]部分)::int
,然后才能转换为NULL
integer
如果版本不遵循此格式,则应将其视为字符串。
。。这并不是对它的定义。那怎么分类呢?最好添加一个具有所需排序顺序的测试用例,以避免歧义。这是真的,我在我的链接中稍微解释了定义。它说的是:“如果您的版本号与此格式不匹配,那么整个版本号将被视为限定符。”我将其解释为主版本号、次版本号和增量版本号的空值。我认为最令人惊讶的排序顺序是先排序空值,这意味着不遵循该格式的版本应该是第一个(正确格式化>正确格式化)。另一个原因是,如果反过来是真的,格式不正确的版本总是会被解释为最新的。很好的解决方案,比我最好的尝试要好得多。我可以发现的一个错误是,如果主要、次要或增量不是数字,例如,在13a.5.6-SNAPSHOT中,正则表达式将不会拾取“a”。另一个问题是,如果格式根本不正确(例如,如果版本只是一个类似“asffdgsdg”的字符串),那么它将被排在最后,这意味着它将始终被解释为最新版本(我知道这部分在我的问题中不清楚)。所以这两个都应该是第一个(正确格式化>错误格式化)@Casper:注意添加的高级解决方案。
SELECT *, part[1] AS p1, part[2] AS p2, part[3] AS p3, part[4] AS p4
, part[5] AS p5, part[6] AS p6, part[7] AS p7
FROM (
SELECT test_id, version, regexp_matches(version
, '^(?:(\d+)(\w*)\.?(\d*)(\w*)\.?(\d*)(\w*))?(?:\-*(\w+))?') AS part
FROM (
VALUES
(1, '1.2.3-SNAPSHOT')
, (2, '2-FOO')
, (3, '2-BAR')
, (4, '2.1-BAR')
, (5, '13.5.6-SNAPSHOT')
, (6, '13.11.11-SNAPSHOT')
, (7, '13.11a.11-SNAPSHOT')
, (8, '13.11b.11')
, (9, 'Test')
, (10, 'TEST2')
, (11, '1a')
, (12, '1a.1a.1a-foo')
, (13, '1a.1a.1b-foo')
, (14, 'sp9d8hgf')
, (15, '2a-BAR')
, (16, '2.1a-BAR')
, (17, '2.1ab-BAR')
, (18, 'incorrect1.2-foo')
) x(test_id, version)
) sub
ORDER BY NULLIF(part[1],'')::int NULLS LAST
, part[2] NULLS FIRST
, NULLIF(part[3],'')::int NULLS FIRST
, part[4] NULLS FIRST
, NULLIF(part[5],'')::int NULLS FIRST
, part[6] NULLS FIRST
, part[7] NULLS FIRST;