sql >> Database >  >> RDS >> PostgreSQL

CASE gebruiken in PostgreSQL om meerdere kolommen tegelijk te beïnvloeden

1. Standaard-SQL:LEFT JOIN een enkele rij met waarden

Je zou kunnen LEFT JOIN een rij waarden met behulp van de voorwaarde (waardoor deze één keer wordt geëvalueerd). Dan kun je fallback-waarden per kolom toevoegen met COALESCE() .

Deze syntaxisvariant is korter en iets sneller met meerdere waarden - vooral interessant voor een dure / langdurige voorwaarde:

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;

Sinds de afgeleide tabel x bestaat uit een enkele rij, meedoen zonder verdere voorwaarden is prima.

Expliciete typecasts zijn nodig in de subquery. Ik gebruik text in het voorbeeld (wat sowieso de standaard is voor letterlijke tekenreeksen). Gebruik uw werkelijke gegevenstypen. De syntaxissneltoets value::type is Postgres-specifiek, gebruik cast(value AS type) voor standaard SQL.

Als de voorwaarde niet TRUE is , alle waarden in x zijn NULL en COALESCE begint.

Of , aangezien alle kandidaatwaarden afkomstig zijn uit tabel rtd2 in uw specifieke geval, LEFT JOIN naar rtd2 met behulp van de originele CASE voorwaarde en CROSS JOIN naar een rij met standaardwaarden:

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;

Het hangt af van de deelnamevoorwaarden en de rest van de zoekopdracht.

2. PostgreSQL-specifiek

2a. Een array uitbreiden

Als uw verschillende kolommen hetzelfde gegevenstype delen , kunt u een array in een subquery gebruiken en deze uitbreiden in de buitenste 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;

Het wordt ingewikkelder als de kolommen niet hetzelfde gegevenstype delen. Je kunt ze allemaal casten naar text (en optioneel terug converteren in de buitenste SELECT ), of je kunt ...

2b. Een rijtype ontleden

U kunt een aangepast samengesteld type (rijtype) gebruiken om waarden van verschillende typen vast te houden en deze eenvoudig *-uit te breiden in de buitenste SELECT . Stel dat we drie kolommen hebben:text , integer en date . Voor herhaald gebruik, maak een aangepast composiettype:

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

Of als het type van een bestaande tabel overeenkomt, kunt u de tabelnaam gewoon als samengesteld type gebruiken.

Of als je het type slechts tijdelijk nodig hebt , kunt u een TEMPORARY TABLE . maken , die een tijdelijk type registreert voor de duur van uw sessie :

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

Je zou dit zelfs kunnen doen voor een enkele transactie :

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

Dan kunt u deze zoekopdracht gebruiken:

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;

Of zelfs gewoon (hetzelfde als hierboven, eenvoudiger, korter, misschien minder gemakkelijk te begrijpen):

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

De CASE expressie wordt op deze manier voor elke kolom eenmaal geëvalueerd. Als de evaluatie niet triviaal is, zal de andere variant met een subquery sneller zijn.



  1. Meerdere rangen in één tabel

  2. Hoe krijg ik een leeftijd uit een D.O.B-veld in MySQL?

  3. Rijnummering met p:dataTable

  4. controleer of e-mail bestaat in de MySQL-database