PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Използване на CASE в PostgreSQL за въздействие върху няколко колони наведнъж

1. Standard-SQL:LEFT JOIN един ред от стойности

Можете да LEFT JOIN ред от стойности, използвайки условието (като по този начин го оценява веднъж). След това можете да добавите резервни стойности на колона с COALESCE() .

Този вариант на синтаксис е по-кратък и малко по-бърз с множество стойности - особено интересен за скъпо/продължително условие:

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;

Тъй като получената таблица x се състои от единичен ред, присъединяването без допълнителни условия е добре.

Явни преобразувания на типове са необходими в подзаявката. Използвам text в примера (което така или иначе е по подразбиране за низови литерали). Използвайте действителните си типове данни. Синтаксисът за бърз достъп value::type е специфичен за Postgres, използвайте cast(value AS type) за стандартен SQL.

Ако условието не е TRUE , всички стойности в x са NULL и COALESCE влиза.

Или , тъй като всички кандидат стойности идват от таблица rtd2 във вашия конкретен случай, LEFT JOIN към rtd2 използвайки оригиналния CASE условие и CROSS JOIN към ред със стойности по подразбиране:

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;

Зависи от условията за присъединяване и останалата част от заявката.

2. Специфично за PostgreSQL

2a. Разгъване на масив

Ако различните ви колони споделят един и същи тип данни , можете да използвате масив в подзаявка и да го разширите във външния 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;

Става по-сложно, ако колоните не споделят един и същи тип данни. Можете или да ги прехвърлите всички към text (и по желание конвертирайте обратно във външния SELECT ), или можете ...

2б. Декомпозиране на тип ред

Можете да използвате персонализиран съставен тип (тип ред), за да съхранявате стойности от различни типове и просто *-да го разширите във външния SELECT . Да кажем, че имаме три колони:text , integer и date . За повторени използвайте, създайте персонализиран съставен тип:

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

Или ако типът на съществуваща таблица съвпада, можете просто да използвате името на таблицата като съставен тип.

Или ако имате нужда само от типа временно , можете да създадете TEMPORARY TABLE , който регистрира временен тип за продължителността на вашата сесия :

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

Можете дори да направите това за една транзакция :

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

Тогава можете да използвате тази заявка:

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;

Или дори просто (същото като по-горе, по-просто, по-кратко, може би не толкова лесно за разбиране):

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 изразът се оценява веднъж за всяка колона по този начин. Ако оценката не е тривиална, другият вариант с подзаявка ще бъде по-бърз.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да конвертирате низ в unicode с помощта на PostgreSQL?

  2. Коя колона за външен ключ:id или друга колона и защо?

  3. Получавам pg грешка, когато се опитвам да унищожа контролер

  4. Как да определите автоматично генерирания първичен ключ, използван като външен ключ за друга таблица

  5. Еквивалент на Group_concat в postgresql 8.2.11