sql >> Databasteknik >  >> RDS >> PostgreSQL

Kombinera två kolumner och lägg till en ny kolumn

Generellt håller jag med om @kgrittns råd. Gör det.

Men för att ta itu med din grundläggande fråga om concat() :Den nya funktionen concat() är användbart om du behöver hantera nullvärden - och null har varken uteslutits i din fråga eller i den du refererar till.

Om du kan utesluta nollvärden, den gamla goda (SQL-standard) sammanfogningsoperatorn || är fortfarande det bästa valet, och @luis svar är bara bra:

SELECT col_a || col_b;

Om någon av dina kolumner kan vara null, resultatet skulle vara null i så fall. Du kan försvara med COALESCE :

SELECT COALESCE(col_a, '') || COALESCE(col_b, '');

Men det blir snabbt tråkigt med fler argument. Det är där concat() kommer in, vilket aldrig returnerar null, inte ens om alla argumenten är ogiltiga. Per dokumentation:

NULL-argument ignoreras.

SELECT concat(col_a, col_b);

Det återstående hörnfodralet för båda alternativen är alla indatakolumner är null i så fall får vi fortfarande en tom sträng '' , men man kanske vill ha null istället (åtminstone jag skulle). Ett möjligt sätt:

SELECT CASE
          WHEN col_a IS NULL THEN col_b
          WHEN col_b IS NULL THEN col_a
          ELSE col_a || col_b
       END;

Detta blir mer komplext med fler kolumner snabbt. Återigen, använd concat() men lägg till en check för specialvillkoret:

SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
            ELSE concat(col_a, col_b) END;

Hur fungerar det här?
(col_a, col_b) är förkortad notation för ett radtypsuttryck ROW (col_a, col_b) . Och en radtyp är bara null om alla kolumner är null. Detaljerad förklaring:

  • INTE NULL-begränsning över en uppsättning kolumner

Använd även concat_ws() för att lägga till avgränsare mellan element (ws för "med separator").

Ett uttryck som det i Kevins svar:

SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;

är tråkigt att förbereda sig för nullvärden i PostgreSQL 8.3 (utan concat() ). Ett sätt (av många):

SELECT COALESCE(
         CASE
            WHEN $1.zipcode IS NULL THEN $1.city
            WHEN $1.city    IS NULL THEN $1.zipcode
            ELSE $1.zipcode || ' - ' || $1.city
         END, '')
       || COALESCE(', ' || $1.state, '');

Funktionsvolatiliteten är endast STABLE

concat() och concat_ws() är STABLE funktioner, inte IMMUTABLE eftersom de kan anropa datatyputgångsfunktioner (som timestamptz_out ) som beror på språkinställningar.
Förklaring av Tom Lane.

Detta förbjuder deras direkta användning i indexuttryck. Om du vet att resultatet faktiskt är oföränderligt i ditt fall, kan du kringgå detta med en IMMUTABLE funktionsomslag. Exempel här:

  • Stöder PostgreSQL "accentokänsliga" sammanställningar?


  1. Skillnaden mellan LIKE och =i MYSQL?

  2. Hur visar jag en bild från blob-kolumnen i Oracle med JasperReports?

  3. Hibernate, Postgresql:Kolumn x är av typen oid men uttrycket är av typen byte

  4. Infoga ett Python datetime.datetime-objekt i MySQL