split_part()
returnerar den tomma strängen ('' ) - inte NULL - när delen som ska returneras är tom eller obefintlig. Det är därför COALESCE
gör inget här. Och den tomma strängen ('' ) har ingen representation som heltal värde, därför ger det ett fel när det försöker casta det.
Den kortaste vägen i det här exemplet bör vara GREATEST(split_part( ... ), '0')
före casting, eftersom den tomma strängen sorterar före någon annan icke-tom sträng eller till och med NULL (i valfri lokalitet). Använd sedan DISTINCT ON () för att få raden med den "största" versionen för varje id .
Testa installationen
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');
Lösningar
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
Resultat:
id | version
----+---------
10 | 10-111
11 | 10-2
Eller du kunde använd även NULLIF och använd NULL LAST (i fallande ordning) för att sortera:
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Samma resultat.
Eller ett mer explicit CASE uttalande:
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle här
Relaterat:
- Beställ varchar-sträng som numerisk
- Välj först rad i varje GROUP BY-grupp?
- PostgreSQL sortera efter datumtid asc, null först?
- Hur man konvertera tomt till null i PostgreSQL?