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?