split_part()
renvoie la chaîne vide (''
) - pas NULL
- lorsque la pièce à restituer est vide ou inexistante. C'est pourquoi COALESCE
ne fait rien ici. Et la chaîne vide (''
) n'a pas de représentation en tant que integer
valeur, par conséquent, il génère une erreur lors de la tentative de conversion.
Le chemin le plus court dans cet exemple devrait être GREATEST(split_part( ... ) , '0')
avant le transtypage, car la chaîne vide est triée avant toute autre chaîne non vide ou même NULL (dans n'importe quelle locale). Ensuite, utilisez DISTINCT ON ()
pour obtenir la ligne avec la "plus grande" version
pour chaque id
.
Configuration du test
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');
Solutions
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;
Résultat :
id | version
----+---------
10 | 10-111
11 | 10-2
Ou tu pourrais utilisez également NULLIF
et utilisez NULLS LAST
(par ordre décroissant) pour trier :
SELECT DISTINCT ON (id) *
FROM tbl
ORDER BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;
Même résultat.
Ou un CASE
plus explicite déclaration :
CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END
dbfiddle ici
Connexe :
- Ordre varchar chaîne comme numérique
- Sélectionner d'abord rangée dans chaque groupe GROUP BY ?
- Tri PostgreSQL par date/heure asc, null en premier ?
- Comment convertir vide en null dans PostgreSQL ?