split_part() 返回空字符串 ('') - 不是 NULL - 当要返回的部分为空或不存在时。这就是为什么COALESCE 在这里什么都不做。并且空字符串 ('') 没有表示为 integer 值,因此在尝试强制转换时会引发错误。
这个例子中最短的方法应该是GREATEST(split_part( ... ) , '0'),因为空字符串在任何其他非空字符串甚至NULL(在任何语言环境中)之前排序。然后使用DISTINCT ON () 为每个id 获取具有“最大”version 的行。
测试设置
CREATE TABLE tbl (
id integer NOT NULL
, version text NOT NULL
);
INSERT INTO tbl VALUES
(10, '10-2')
, (10, '10-1')
, (10, '10') -- missing subversion
, (10, '10-111') -- multi-digit number
, (11, '11-1')
, (11, '11-0') -- proper '0'
, (11, '11-') -- missing subversion but trailing '-'
, (11, '11-2');
解决方案
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
结果:
id | version
----+---------
10 | 10-111
11 | 10-2
或者你也可以使用NULLIF和NULLS LAST(按降序排列)进行排序:
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
同样的结果。
或者更明确的CASE声明:
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle here
相关: