split_part()
devuelve la cadena vacía ('' ) - no NULL - cuando la pieza a devolver esté vacía o no exista. Por eso COALESCE
hace nada aquí. Y la cadena vacía ('' ) no tiene representación como integer valor, por lo tanto, arroja un error al intentar lanzarlo.
El camino más corto en este ejemplo debería ser GREATEST(split_part( ... ) , '0')
antes de la conversión, ya que la cadena vacía se ordena antes que cualquier otra cadena no vacía o incluso NULL (en cualquier configuración regional). Luego use DISTINCT ON () para obtener la fila con la version "mayor" para cada id .
Configuración de prueba
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');
Soluciones
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
Resultado:
id | version
----+---------
10 | 10-111
11 | 10-2
O usted podría también use NULLIF y use NULLS LAST (en orden descendente) para ordenar:
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Mismo resultado.
O un CASE más explícito declaración:
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle aquí
Relacionado:
- Ordenar cadena varchar como numérico
- Seleccionar primero fila en cada grupo GROUP BY?
- PostgreSQL ordenar por fechahora asc, nulo primero?
- Cómo convertir vacío a nulo en PostgreSQL?