Есть ли способ выполнить оператор If Then в предложении join

#sql #left-join #amazon-redshift #where-clause #full-outer-join

#sql #левое соединение #amazon-redshift #where-предложение #full-outer-join

Вопрос:

У меня есть две таблицы, spend и bookings, для которых я пытаюсь выполнить полное объединение. Из-за характера таблиц (не у всех бронирований есть spend , и не у всех spend есть booking_id , а иногда присваивается неправильный booking_id), я хотел бы выполнить условный оператор в предложении join .

 select bk.booking_id, bk.company_id, bk.event_id, bk.total_amount_booked, sp.spend
from 
(select booking_id, company_id, event_id, booked_rate, total_amount_booked
from bookings) bk
full join
(select booking_id, company_id, event_id, normalized_spend, spend
from spend) sp
on (bk.booking_id = sp.booking_id and bk.booked_rate = sp.normalized_spend)
or (bk.company_id = sp.company_id and bk.event_id = sp.event_id);
  

В принципе, если booking_id совпадает, а нормализованный расход соответствует booked_rate, тогда присоединяйтесь к этому условию.
Если нет, присоединяйтесь к company_id и event_id.

Однако выполнение этого запроса возвращает

FULL JOIN is only supported with merge-joinable join conditions;

Есть ли лучший способ сделать это? Использование Redshift

Комментарии:

1. В стороне — RedShift не выполняется в PostgreSQL. Это отдельная СУБД, созданная на более раннем диалекте Postgres.

2. DataGrip говорит, что я использую PostgreSQL 8.0.2 на i686-pc-linux-gnu, скомпилированный GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.19097. Я предполагаю, что это более старая версия Postgres, но есть некоторые функции, которые вы не можете выполнить в Redshift, которые вы можете выполнить в PostgreSQL.

Ответ №1:

Это немного болезненно, но вы можете эмулировать full соединение с помощью двух left joins и union all :

 select bk.booking_id, bk.company_id, bk.event_id, bk.total_amount_booked, sp.spend
from bookings bk
left join spend sp
    on (bk.booking_id = sp.booking_id and bk.booked_rate = sp.normalized_spend)
    or (bk.company_id = sp.company_id and bk.event_id = sp.event_id)
union all
select bk.booking_id, bk.company_id, bk.event_id, bk.total_amount_booked, sp.spend
from spend sp
left join bookings bk
    on (bk.booking_id = sp.booking_id and bk.booked_rate = sp.normalized_spend)
    or (bk.company_id = sp.company_id and bk.event_id = sp.event_id)
where bk.booking_id is null
  

Ответ №2:

Возможно, используя оператор CASE, что-то вроде

 ...ON CASE WHEN (bk.booking_id = sp.booking_id and bk.booked_rate = sp.normalized_spend)
          THEN (bk.booking_id = sp.booking_id and bk.booked_rate = sp.normalized_spend)
         WHEN (bk.company_id = sp.company_id and bk.event_id = sp.event_id) 
          THEN (bk.company_id = sp.company_id and bk.event_id = sp.event_id)
    END
  

Комментарии:

1. Это выдает ту же ошибку «ПОЛНОЕ ОБЪЕДИНЕНИЕ поддерживается только с условиями объединения, совместимыми с объединением»