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?