sql >> Database teknologi >  >> RDS >> PostgreSQL

Brug af CASE i PostgreSQL til at påvirke flere kolonner på én gang

1. Standard-SQL:LEFT JOIN en enkelt række med værdier

Du kunne LEFT JOIN en række af værdier ved hjælp af betingelsen (derved evalueres den én gang). Derefter kan du tilføje fallback-værdier pr. kolonne med COALESCE() .

Denne syntaksvariant er kortere og lidt hurtigere med flere værdier - især interessant for en dyr / langvarig tilstand:

SELECT COALESCE(x.txt1, trim(r2.team_name))     AS testing_testing
     , COALESCE(x.txt2, trim(r2.normal_data))   AS test_response
     , COALESCE(x.txt3, trim(r2.normal_data_2)) AS another_example
FROM   rtp
JOIN   rtd2 r2 ON <unknown condition> -- missing context in question
LEFT   JOIN (
   SELECT 'testing'::text         AS txt1
        , 'test example'::text    AS txt2
        , 'test example #2'::text AS txt3
   ) x ON rtp.team_id = rtp.sub_team_id;

Siden den afledte tabel x består af en enkelt række, er det fint at deltage uden yderligere betingelser.

Explicit type casts er nødvendige i underforespørgslen. Jeg bruger text i eksemplet (som alligevel er standard for strenge bogstaver). Brug dine faktiske datatyper. Syntaksgenvejen value::type er Postgres-specifik, brug cast(value AS type) for standard SQL.

Hvis betingelsen ikke er TRUE , alle værdier i x er NULL og COALESCE slår ind.

Eller , da alle kandidatværdier kommer fra tabel rtd2 i dit særlige tilfælde LEFT JOIN til rtd2 ved at bruge den originale CASE betingelse og CROSS JOIN til en række med standardværdier:

SELECT COALESCE(trim(r2.team_name),     x.txt1) AS testing_testing
     , COALESCE(trim(r2.normal_data),   x.txt2) AS test_response
     , COALESCE(trim(r2.normal_data_2), x.txt3) AS another_example
FROM   rtp
LEFT   JOIN rtd2 r2 ON <unknown condition>  -- missing context in question
                   AND rtp.team_id = rtp.sub_team_id
CROSS  JOIN (
   SELECT 'testing'::text         AS txt1
        , 'test example'::text    AS txt2
        , 'test example #2'::text AS txt3
   ) x;

Det afhænger af joinbetingelserne og resten af ​​forespørgslen.

2. PostgreSQL-specifik

2a. Udvid en matrix

Hvis dine forskellige kolonner deler samme datatype , kan du bruge et array i en underforespørgsel og udvide det i den ydre SELECT :

SELECT x.combo[1], x.combo[2], x.combo[3]
FROM  (
   SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
            THEN '{test1,test2,test3}'::text[]
            ELSE ARRAY[trim(r2.team_name)
                     , trim(r2.normal_data)
                     , trim(r2.normal_data_2)]
          END AS combo
   FROM   rtp
   JOIN   rtd2 r2 ON <unknown condition>
   ) x;

Det bliver mere kompliceret, hvis kolonnerne ikke deler den samme datatype. Du kan enten caste dem alle til text (og konverter eventuelt tilbage i den ydre SELECT ), eller du kan ...

2b. Dekomponer en rækketype

Du kan bruge en brugerdefineret sammensat type (rækketype) til at holde værdier af forskellige typer og simpelthen *-udvide den i den ydre SELECT . Lad os sige, at vi har tre kolonner:text , integer og date . Til gentaget brug, opret en brugerdefineret sammensat type:

CREATE TYPE my_type (t1 text, t2 int, t3 date);

Eller hvis typen af ​​en eksisterende tabel matcher, kan du bare bruge tabelnavnet som sammensat type.

Eller hvis du kun har brug for typen midlertidigt , kan du oprette en TEMPORARY TABLE , som registrerer en midlertidig type for varigheden af ​​din session :

CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);

Du kan endda gøre dette for en enkelt transaktion :

CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;

Så kan du bruge denne forespørgsel:

SELECT (x.combo).*  -- parenthesis required
FROM  (
   SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
             THEN ('test', 3, now()::date)::my_type  -- example values
             ELSE (r2.team_name
                 , r2.int_col
                 , r2.date_col)::my_type
          END AS combo
   FROM   rtp
   JOIN   rtd2 r2 ON <unknown condition>
   ) x;

Eller endda bare (samme som ovenfor, enklere, kortere, måske mindre let at forstå):

SELECT (CASE WHEN rtp.team_id = rtp.sub_team_id
           THEN ('test', 3, now()::date)::my_type
           ELSE (r2.team_name, r2.int_col, r2.date_col)::my_type
        END).*
FROM   rtp
JOIN   rtd2 r2 ON <unknown condition>;

CASE udtryk evalueres én gang for hver kolonne på denne måde. Hvis evalueringen ikke er triviel, vil den anden variant med en underforespørgsel være hurtigere.



  1. Gruppering af en kommasepareret værdi på fælles data

  2. JUnit/HSQLDB:Sådan kommer du uden om fejl med Oracle-syntaks, når du tester med HSQLDB (ingen privilegium og/eller intet DUAL-objekt)

  3. Vis alle triggere i Oracle-databasen

  4. Eliminer duplikerede resultater i en udvalgt forespørgsel, der indeholder CLOB-kolonnen