解析字符串。喜欢:
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;
->SQLfiddle 演示。
substring(version, '^(\d+)')
.. 使用substring()
正则表达式模式进行解析。
^
.. 字符串开头
()
.. 捕获括号
\d
.. 类数字速记
substring(version, '^(\d+)')::int
.. 转换为整数以像数字一样排序
major NULLS LAST
.. 没有编号的版本排在最后(我的假设)。
minor NULLS FIRST
..2
来之前2.1
NULLS LAST
是默认值,ORDER BY
可以省略。
您可以直接使用这些表达式ORDER BY
。只是为了更好的可读性而演示。
先进的解决方案
对于更复杂的规则,您可能需要使用regexp_matches()
:
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;
-> SQL小提琴
这涉及您评论中的所有附加规则。
regexp_matches()
是一个强大的工具,但你需要对正则表达式有基本的了解。如有疑问,请测试。
特别注意:
- 不加
g
开关。更多在这里。
()
请注意捕获括号和非捕获括号之间的区别(:?)
。
NULLIF(part[1],'')::int
.. 不匹配项在数组中列为空字符串。需要在转换为NULL
之前转换为integer