解决子选择中的模糊列

时间:2015-03-30 21:30:36

标签: sql postgresql join subquery left-join

我在使用ON联接表达式语法从两个已连接表之间具有共享名称的子选择中选择列时遇到问题。

我有两个表eventgeography,每个表都有一个geography_id列,它是相同的数据类型,event.geography_id是一个外键{ {1}}(地理位置提供有关活动的信息):

simplified ERD from Dia

我遇到的问题是,当使用geography语法加入这两个表时,我无法引用这两个表之间的共享列,但在使用ON时它可以正常工作语法。

我意识到USING的作用是因为它suppresses redundant columns,但由于该语句使用了许多不同的连接表,而且模式的更改频率更高,我宁愿尽可能明确。

我遇到问题的具体SQL是:

USING

出现错误:

  

错误:列引用" geography_id"含糊不清

     

第8行:(1,2,3)中的x.geography_id

我正在使用PostgreSQL 9.0.14。

3 个答案:

答案 0 :(得分:4)

在SQL中,能够选择之外的一个或多个明确要排除的列时,这将是一个非常有用的功能。如果它存在,您可以使用此功能通过排除g.geography_id来解决您的问题。不幸的是,在任何DBMS中,这样的功能似乎都不存在。请参阅https://dba.stackexchange.com/questions/1957/sql-select-all-columns-except-some

一个解决方案,如@a_horse_with_no_name所述,是列出您要选择的每一列,只省略您不想要的那些。

实际上还有另一种可能更好的解决方案,即选择*e.geography_id,但将后者别名为另一个名称,该名称在子查询结果集中将是明确的。像这样:

select
    x.event_id
from (
    select *, e.geography_id geography_id1 from event e
    left join geography g on (e.geography_id = g.geography_id)
) x
where
    x.geography_id1 in (1,2,3)

答案 1 :(得分:0)

您可以将查询编写为:

select
    e.event_id
from event e
    left join geography g 
      on (e.geography_id = g.geography_id)
where
    e.geography_id in (1,2,3)

这应该在逻辑上等效,或切换到:

where
    g.geography_id in (1,2,3)

获得只有匹配的回报(这会问为什么不使用内部联接)

答案 2 :(得分:0)

在加入之前将谓词向下拉入子查询

SELECT e.event_id
FROM  (SELECT * FROM event WHERE geography_id IN (1,2,3)) e
LEFT   JOIN geography g ON (g.geography_id = e.geography_id);

结果与原始查询100%相同:

SELECT e.event_id
FROM   event e
LEFT   JOIN geography g USING (geography_id)
WHERE  geography_id in (1,2,3);

只是替代方案应该更快(尽早排除不相关的行)。对于变通方法来说,这是一个可接受的副作用。