2015-03-30 49 views
3

我在使用ON连接表达式语法从两个连接表之间共享名称的子查询中选择一列时遇到问题。解决子查询中模糊列的问题

我有两个表,eventgeography的每一个具有一个geography_id柱,这是相同的数据类型,和event.geography_id为外键入geography(地理提供关于事件的信息):

simplified ERD from Dia

我遇到的问题是,当使用ON语法加入它们时,我无法引用这两个表格之间的共享列,但它在使用USING语法时有效。

我意识到USING的作品,因为它suppresses redundant columns,但自言使用许多不同的连接表与多不经常改变的模式,我宁愿尽可能明确。

我遇到问题的特定SQL是:

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

这给错误:

ERROR: column reference "geography_id" is ambiguous

LINE 8: x.geography_id in (1,2,3)

我使用PostgreSQL 9.0.14。

+1

您需要在派生表中单独列出每个列(子选择)。这是'使用'条款的唯一选择。 – 2015-03-30 21:32:36

回答

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) 
+0

这是最干净的解决方案,也是唯一不涉及重构整个查询的解决方案。 – amphetamachine 2015-04-01 14:43:48

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) 

得到回报,只有有比赛(这会问为什么不使用内部连接)

+0

无法使用内部联接,因为'geography_id' where子句是可选的(如果未指定,返回所有事件,而不管它们是否具有地理位置),并且“x.geography_id为null”也是可能的子句。 – amphetamachine 2015-03-30 21:51:58

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); 

只是,替代要快很多(早期排除不相关的行)。解决方法相当可接受的副作用。