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.