1. Standard-SQL:LEFT JOIN
en enda rad med värden
Du kan LEFT JOIN
en rad med värden som använder villkoret (och utvärderar det en gång). Sedan kan du lägga till reservvärden per kolumn med COALESCE()
.
Denna syntaxvariant är kortare och något snabbare med flera värden - speciellt intressant för ett dyrt/långt tillstånd:
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;
Eftersom den härledda tabellen x
består av en singel rad, går det bra att gå med utan ytterligare villkor.
Explicita casts är nödvändiga i underfrågan. Jag använder text
i exemplet (vilket är standard för strängliterals ändå). Använd dina faktiska datatyper. Syntaxgenvägen value::type
är Postgres-specifik, använd cast(value AS type)
för standard SQL.
Om villkoret inte är TRUE
, alla värden i x
är NULL och COALESCE
slår in.
Eller , eftersom alla kandidatvärden kommer från tabellen rtd2
i ditt specifika fall, LEFT JOIN
till rtd2
med den ursprungliga CASE
condition och CROSS JOIN
till en rad med standardvärden:
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 beror på anslutningsvillkoren och resten av frågan.
2. PostgreSQL-specifik
2a. Expandera en array
Om dina olika kolumner delar samma datatyp , kan du använda en array i en underfråga och expandera den i den yttre 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 blir mer komplicerat om kolumnerna inte delar samma datatyp. Du kan antingen casta dem alla till text
(och eventuellt konvertera tillbaka i den yttre SELECT
), eller så kan du ...
2b. Dekomponera en radtyp
Du kan använda en anpassad sammansatt typ (radtyp) för att hålla värden av olika typer och helt enkelt *-expandera den i den yttre SELECT
. Säg att vi har tre kolumner:text
, integer
och date
. För upprepade använd, skapa en anpassad sammansatt typ:
CREATE TYPE my_type (t1 text, t2 int, t3 date);
Eller om typen av en befintlig tabell matchar kan du bara använda tabellnamnet som sammansatt typ.
Eller om du bara behöver typen tillfälligt , kan du skapa en TEMPORARY TABLE
, som registrerar en tillfällig typ under din session :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
Du kan till och med göra detta för en enskild transaktion :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
Sedan kan du använda den här frågan:
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 till och med bara (samma som ovan, enklare, kortare, kanske mindre lätt att förstå):
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
uttryck utvärderas en gång för varje kolumn på detta sätt. Om utvärderingen inte är trivial blir den andra varianten med en underfråga snabbare.