postgres: попытка объединить 4 таблицы на основе условного
У меня есть 4 таблицы. В table1 есть один столбец с именем reportable_type и другой столбец с именем reportable_id. Тип отчета имеет два значения: table2 или table3. У table2 и table3 есть столбец для table4_id. Я пытаюсь написать запрос, который получает мне table1.id и table4.description в одном результате. Такое ощущение, что заявление о кейсах на postgres может привести меня туда, но я заблудился, также два случая, вероятно, нарушают это:
select t1.id, t4.description
from table1 as t1
case
when t1.reportable_type = ’table2’
then left join table2 as t2 on t1.reportable_id = t2.id
else left join table3 as t3 on t1.reportable_id = t3.id
end
left join table4 as t4 on
case
when t1.reportable_type = ’table2’
then t2.table4_id =t4.id
else t3.table4_id =t4.id
end
group by t4.description;
РЕДАКТИРОВАТЬ:
Желая добавить некоторые данные вокруг этого, чтобы было понятнее. Позволяет использовать следующие данные:
table 1
IDs - 1, 2
reportable_type - table 2, table 3
reportable_id - 1, 1
table 2:
id - 1
t4_id - 1
table 3:
id - 1
t4_id - 2
table 4:
id - 1 ,2
description - first, second
Таким образом, результирующая таблица из запроса должна быть:
id - 1,2
description - first, second
1 ответ
Мы должны оставить соединение на t2 и t3, зная, что только 1 разрешит, так как t1.reportable_Type не может быть <> 'table2' и = table2. Тогда мы можем coalesce
значение для отношения к t4 от любого ID в T3, t2.
Это означает, что оба левых объединения должны пытаться быть разрешенными, поэтому это может быть не так эффективно, как попытка выяснить, как выполнить только одно из левых объединений. Но результаты должны быть точными. Как только вы это заработаете, если производительность является проблемой, нам нужно будет рассмотреть планы / индексы выполнения, чтобы увидеть, есть ли другой способ ее оптимизации.
SELECT t1.id, t4.description
FROM table1 as t1
LEFT join table2 as t2
on t1.reportable_id = t2.id
and t1.reportable_type = 'table2'
LEFT join table3 as t3
on t1.reportable_id = t3.id
and coalesce(t1.reportable_type,'isNull') <> 'table2'
LEFT join table4 as t4
on t4.id = coalesce(t2.table4_id, t3.table4_ID)
--GROUP BY t4.description;
Не уверен, почему у вас есть группа без агрегации. поэтому я закомментировал это; может ты имеешь ввиду ORDER BY
; Я обычно считаю целесообразным включать order by почти во все запросы; особенно те, которые могут использовать индексы.
Я также добавил and coalesce(t1.reportable_type,'isNull') <> 'table2'
использовать coalesce для обработки ситуации, если t1.reportable_type имеет значение null. Я предполагаю, что вы все еще хотели бы, чтобы эти записи, поскольку нуль не равен 'table2', но вы можете вообще не хотеть этих записей; поэтому нам нужно больше информации об этом конкретном случае.
Условие соединения <> в t3 также может немного подорвать производительность, поскольку я не верю, что индекс можно использовать. но я не уверен, как обойти это, но, возможно, есть или существует, и подзапрос будет работать... но я позволю вам играть отсюда.