1. Standard-SQL:LEFT JOIN
pojedynczy rząd wartości
Możesz LEFT JOIN
wiersz wartości przy użyciu warunku (a tym samym jednokrotne obliczenie). Następnie możesz dodać wartości rezerwowe na kolumnę za pomocą COALESCE()
.
Ten wariant składni jest krótszy i nieco szybszy z wieloma wartościami - szczególnie interesujący w przypadku drogiego/długiego stanu:
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;
Ponieważ tabela pochodna x
składa się z singli wiersz, łączenie bez dalszych warunków jest w porządku.
Wyraźne rzuty typu są niezbędne w podzapytaniu. Używam text
w przykładzie (co i tak jest domyślne dla literałów łańcuchowych). Użyj swoich rzeczywistych typów danych. Skrót składni value::type
jest specyficzny dla Postgresa, użyj cast(value AS type)
dla standardowego SQL.
Jeśli warunek nie jest TRUE
, wszystkie wartości w x
są NULL i COALESCE
wskakuje.
Lub , ponieważ wszystkie wartości kandydujące pochodzą z tabeli rtd2
w Twoim konkretnym przypadku LEFT JOIN
do rtd2
używając oryginalnego CASE
warunek i CROSS JOIN
do wiersza z wartościami domyślnymi:
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;
Zależy to od warunków przyłączenia i reszty zapytania.
2. Specyficzne dla PostgreSQL
2a. Rozwiń tablicę
Jeśli różne kolumny mają ten sam ten sam typ danych , możesz użyć tablicy w podzapytaniu i rozwinąć ją w zewnętrznym 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;
Sprawa się komplikuje, jeśli kolumny nie mają tego samego typu danych. Możesz przesłać je wszystkie do text
(i opcjonalnie przekonwertuj z powrotem w zewnętrznym SELECT
) lub możesz ...
2b. Rozłóż typ wiersza
Możesz użyć niestandardowego typu złożonego (typu wiersza) do przechowywania wartości różnych typów i po prostu *-rozwiń go w zewnętrznym SELECT
. Załóżmy, że mamy trzy kolumny:text
, integer
i date
. Za powtarzane użyj, utwórz niestandardowy typ złożony:
CREATE TYPE my_type (t1 text, t2 int, t3 date);
Lub jeśli typ istniejącej tabeli pasuje, możesz po prostu użyć nazwy tabeli jako typu złożonego.
Lub jeśli potrzebujesz tylko typu tymczasowo , możesz utworzyć TEMPORARY TABLE
, który rejestruje typ tymczasowy na czas trwania Twojej sesji :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
Możesz to zrobić nawet w przypadku pojedynczej transakcji :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
Następnie możesz użyć tego zapytania:
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;
Lub nawet po prostu (tak samo jak powyżej, prostsze, krótsze, może mniej zrozumiałe):
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
wyrażenie jest w ten sposób oceniane raz dla każdej kolumny. Jeśli ocena nie jest trywialna, inny wariant z podzapytaniem będzie szybszy.