仅加入维度表一次

时间:2016-03-11 00:24:47

标签: sql postgresql join

我有一张事实表,我们有OrderId | Arrival_location | Departing_location

链接到此的维度表非常基本,类似于LocationID | LocationName

要进行查询以获取到达和离开的位置名称,我是否必须join两次?

SELECT 
  OrderId, adm.LocationName, dep.LocationName
FROM 
  fct
LEFT JOIN dim as adm
  ON fct.Arrival_location = adm.LocationID
LEFT JOIN dim as dep
  ON fct.Departing_location = dep.LocationID

或者只有一个left join

可以做到这一点

1 个答案:

答案 0 :(得分:2)

您需要两个联接,因为出发和到达地点是独立值

让我们稍微重写一下你的查询来说明。我还会将LEFT JOIN更改为INNER JOIN,因为这样可以更明确地说明这一点:

SELECT 
  OrderId, adm.LocationName, dep.LocationName
FROM 
  fct
INNER JOIN dim
  ON fct.Arrival_location = dim.LocationID
  AND fct.Departing_location = dim.LocationID

在此查询中,您只加入dim一次。但你说的是:

  • fct.Arrival_location = dim.LocationID
  • fct.Departing_location = dim.LocationID

从逻辑上讲,它遵循以下两个:

  • fct.Arrival_location = fct.Departing_location

因此,要表达您的查询所需的逻辑,您需要adm.LocationIDdep.LocationID代表两个可能不同的 LocationID值。这在SQL中的工作方式是,通过在同一个表中使用两个不同的别名,您可以获得类似的效果,就好像您有两个相同的表“副本”一样。结果集中的每一行对应于每个“副本”的独立值选择。所以我的查询是这样的:

  • fct中的每一行:
    • 对于dim中的每一行:
    • 如果行对满足条件,则为该组合输出一行。

而在您的查询中:

  • fct中的每一行:
    • 对于dim中的每一行,别名为adm
    • 对于dim中的每一行,别名为dep
    • 如果行组合满足条件(考虑LEFT JOIN部分),则为该组合输出一行。

因此,通过额外连接,它会考虑所有组合的位置对。