PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Ersetzen des Werts im leeren Feld nach Verwendung von split_part

split_part() gibt den leeren String zurück ('' ) - nicht NULL - wenn das zurückzusendende Teil leer oder nicht vorhanden ist. Deshalb COALESCE macht nichts hier. Und der leere String ('' ) hat keine Darstellung als integer Wert, daher wird ein Fehler ausgegeben, wenn versucht wird, ihn umzuwandeln.

Der kürzeste Weg in diesem Beispiel sollte GREATEST(split_part( ... ) , '0') vor dem Casting, da die leere Zeichenfolge vor jeder anderen nicht leeren Zeichenfolge oder sogar NULL (in jedem Gebietsschema) sortiert wird. Verwenden Sie dann DISTINCT ON () um die Zeile mit der "größten" version zu erhalten für jede id .

Testaufbau

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');

Lösungen

SELECT DISTINCT ON (id) *
FROM   tbl
ORDER  BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;

Ergebnis:

 id | version 
----+---------
 10 | 10-111
 11 | 10-2

Oder Sie könnten Verwenden Sie auch NULLIF und verwenden Sie NULLS LAST (in absteigender Reihenfolge) zu sortieren:

SELECT DISTINCT ON (id) *
FROM   tbl
ORDER  BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;

Gleiches Ergebnis.

Oder ein expliziterer CASE Aussage:

CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END

dbfiddle hier

Verwandte: