split_part()
retorna a string vazia (''
) - não NULL
- quando a parte a ser devolvida estiver vazia ou inexistente. É por isso que COALESCE
não faz nada aqui. E a string vazia (''
) não tem representação como integer
value, portanto, ele gera um erro ao tentar convertê-lo. O caminho mais curto neste exemplo deve ser
GREATEST(split_part( ... ) , '0')
antes da conversão, já que a string vazia é classificada antes de qualquer outra string não vazia ou até mesmo NULL (em qualquer localidade). Em seguida, use DISTINCT ON ()
para obter a linha com a "maior" versão
para cada id
. Configuração do teste
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');
Soluções
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
Ou você poderia também use
NULLIF
e use NULLS LAST
(em ordem decrescente) para classificar:SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Mesmo resultado.
Ou um
CASE
mais explícito declaração:CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle aqui
Relacionado:
- Ordenar a string varchar como numérica
- Selecione primeiro linha em cada grupo GROUP BY?
- Classificação do PostgreSQL por data e hora asc, nulo primeiro?
- Como converter vazio para nulo no PostgreSQL?