sql >> Databáze >  >> RDS >> PostgreSQL

Použití CASE v PostgreSQL k ovlivnění více sloupců najednou

1. Standard-SQL:LEFT JOIN jeden řádek hodnot

Můžete se LEFT JOIN řádek hodnot pomocí podmínky (tím se vyhodnotí jednou). Poté můžete přidat záložní hodnoty pro každý sloupec pomocí COALESCE() .

Tato varianta syntaxe je kratší a o něco rychlejší s více hodnotami – zvláště zajímavá pro drahé / zdlouhavé podmínky:

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;

Od odvozené tabulky x sestává z jednoho řádek, připojení bez dalších podmínek je v pořádku.

Explicitní typ přetypování jsou nutné v poddotazu. Používám text v příkladu (což je stejně výchozí hodnota pro řetězcové literály). Použijte své skutečné datové typy. Zkratka syntaxe value::type je specifické pro Postgres, použijte cast(value AS type) pro standardní SQL.

Pokud podmínka není TRUE , všechny hodnoty v x jsou NULL a COALESCE kopne.

Nebo , protože všechny kandidátní hodnoty pocházejí z tabulky rtd2 ve vašem konkrétním případě LEFT JOIN na rtd2 pomocí původního CASE podmínkou a CROSS JOIN na řádek s výchozími hodnotami:

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;

Záleží na podmínkách spojení a zbytku dotazu.

2. Specifické pro PostgreSQL

2a. Rozbalte pole

Pokud různé sloupce sdílejí stejný typ dat , můžete použít pole v poddotazu a rozšířit ho ve vnějším 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;

Je to složitější, pokud sloupce nesdílejí stejný datový typ. Můžete je všechny přenést do text (a volitelně převést zpět do vnějšího SELECT ), nebo můžete ...

2b. Rozložte typ řádku

Můžete použít vlastní složený typ (typ řádku) k uložení hodnot různých typů a jednoduše jej *-rozbalit ve vnějším SELECT . Řekněme, že máme tři sloupce:text , integer a date . Pro opakované použijte, vytvořte vlastní složený typ:

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

Nebo pokud se typ existující tabulky shoduje, můžete jako složený typ použít pouze název tabulky.

Nebo pokud potřebujete typ pouze dočasně , můžete vytvořit TEMPORARY TABLE , která zaregistruje dočasný typ po dobu trvání vaší relace :

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

Můžete to udělat i pro jedinou transakci :

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

Pak můžete použít tento dotaz:

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;

Nebo dokonce jen (stejně jako výše, jednodušší, kratší, možná méně srozumitelné):

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 výraz je takto vyhodnocen jednou pro každý sloupec. Pokud vyhodnocení není triviální, bude rychlejší druhá varianta s poddotazem.



  1. PDO::PARAM pro typ desítkové?

  2. Jak mohu strukturovat dotaz SQL, abych našel objekt, který je rodičem dvou konkrétních jiných objektů?

  3. Server neodpovídá (nebo není správně nakonfigurován soket místního serveru MySQL) na serveru wamp

  4. Získat všechny názvy tabulek konkrétní databáze pomocí SQL dotazu?