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.