解决子选择中的不明确列
Resolving an ambiguous column in a subselect
我在使用 ON
连接表达式语法从两个连接表之间具有共享名称的子选择中选择列时遇到问题。
我有两个表,event
和geography
各有一个geography_id
列,是相同的数据类型,event.geography_id
是外键进入 geography
(地理提供了有关事件的信息):
我遇到的问题是,在使用 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.
SQL 中的一项非常有用的功能能够 select 所有列 除了 您明确要排除的一列或多列。如果它存在,您可以使用这样的功能通过排除 g.geography_id
来解决您的问题。不幸的是,这样的功能似乎并不存在于任何 DBMS 中。参见 https://dba.stackexchange.com/questions/1957/sql-select-all-columns-except-some。
正如@a_horse_with_no_name 评论的那样,一个解决方案是列出您想要 select 的每一列,并省略您不需要的列。
实际上还有另一个可能更可取的解决方案,即 select *
和 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)
您能否将查询写成:
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)
获得只有匹配项的 returns(这会引出为什么不使用内部联接的问题)
在加入之前将谓词拉入子查询:
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);
只是替代方案应该更快(尽早排除不相关的行)。解决方法的副作用是可以接受的。
我在使用 ON
连接表达式语法从两个连接表之间具有共享名称的子选择中选择列时遇到问题。
我有两个表,event
和geography
各有一个geography_id
列,是相同的数据类型,event.geography_id
是外键进入 geography
(地理提供了有关事件的信息):
我遇到的问题是,在使用 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.
SQL 中的一项非常有用的功能能够 select 所有列 除了 您明确要排除的一列或多列。如果它存在,您可以使用这样的功能通过排除 g.geography_id
来解决您的问题。不幸的是,这样的功能似乎并不存在于任何 DBMS 中。参见 https://dba.stackexchange.com/questions/1957/sql-select-all-columns-except-some。
正如@a_horse_with_no_name 评论的那样,一个解决方案是列出您想要 select 的每一列,并省略您不需要的列。
实际上还有另一个可能更可取的解决方案,即 select *
和 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)
您能否将查询写成:
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)
获得只有匹配项的 returns(这会引出为什么不使用内部联接的问题)
在加入之前将谓词拉入子查询:
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);
只是替代方案应该更快(尽早排除不相关的行)。解决方法的副作用是可以接受的。