split_part()
restituisce la stringa vuota (''
) - non NULL
- quando il pezzo da restituire è vuoto o inesistente. Ecco perché COALESCE
non fa nulla qui. E la stringa vuota (''
) non ha alcuna rappresentazione come integer
value, quindi genera un errore quando si tenta di eseguirne il cast.
La via più breve in questo esempio dovrebbe essere GREATEST(split_part( ... ) , '0')
prima del casting, poiché la stringa vuota viene ordinata prima di qualsiasi altra stringa non vuota o anche NULL (in qualsiasi locale). Quindi usa DISTINCT ON ()
per ottenere la riga con la version
"più grande". per ogni id
.
Impostazione di prova
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');
Soluzioni
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
Risultato:
id | version
----+---------
10 | 10-111
11 | 10-2
Oppure tu potresti usa anche NULLIF
e usa NULLS LAST
(in ordine decrescente) per ordinare:
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Stesso risultato.
Oppure un CASE
più esplicito dichiarazione:
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle qui
Correlati:
- Ordina la stringa varchar come numerica
- Seleziona prima riga in ogni gruppo GROUP BY?
- PostgreSQL ordina per data/ora asc, null prima?
- Come fare per convertire vuoto in null in PostgreSQL?