postgres:尝试根据条件加入4个表

时间:2017-06-30 12:59:15

标签: postgresql join case

我有4张桌子。 table1有一列名为reportable_type,另一列名为reportable_id。 reportable类型有两个值,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 个答案:

答案 0 :(得分:3)

我们必须在t2和t3上保持联接,因为t1.reportable_Type不能是<> 'table2'和= table2。然后我们可以从T3,t2中的任一ID coalesce {t}与t4的关系值。

这确实意味着左边连接都必须尝试解析,因此它可能不如试图找出如何只执行其中一个左连接那样高效。但结果应该准确。一旦你开始工作,如果性能是一个问题,我们需要查看执行计划/索引,看看是否有另一种方法来优化它。

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;我通常认为在几乎所有查询中都包含订单是明智的;特别是那些可以使用索引的那些。

如果t1.reportable_type为null,我还添加了and coalesce(t1.reportable_type,'isNull') <> 'table2'来使用coalesce来处理这种情况。我假设您仍然希望那些记录为null的记录不等于'table2',但您可能根本不想要那些记录;所以我们需要有关该特定案例的更多信息。

&lt;&gt;因为我不相信可以使用索引,所以t3上的连接条件也可能有点性能。但是我不知道如何解决这个问题,但也许是in或者存在,子查询会起作用......但我会让你从这里开始玩。