sql – IN子查询的WHERE条件影响主查询 – 这是一个功能还是一个错误?

假设有两个表:
Table A: A1,A2,A_Other
Table B: B1,B2,B_Other

在以下示例中,是针对固定值检查的条件,例如,=’ABC’或< 45. 我写了一个如下(1)的查询

Select * from A
Where A1 IN (
    Select distinct B1 from B
    Where B2 is something
    And A2 is something
);

我真正打算写的是(2):

Select * from A
Where A1 IN (
    Select distinct B1 from B
    Where B2 is something
)
And A2 is something;

奇怪的是,两个查询都返回了相同的结果.在查看查询1的解释计划时,看起来就像执行子查询时一样,因为条件A2不适用于子查询,它被推迟用作主查询结果的过滤器.

我通常希望查询1失败,因为子查询本身会失败:

Select distinct B1 from B
Where B2 is something
And A2 is something; --- ERROR:  column "A2" does not exist

但我发现情况并非如此,Postgres将不适用的子查询条件推迟到主查询.

这是标准行为还是Postgres异常?这记录在哪里,这个功能叫做什么?

此外,我发现如果我在表B中添加列A2,则只有查询2按预期工作.在这种情况下,查询2中的引用A2仍将引用A.A2,但查询1中的引用将引用新列B.A2,因为它现在可直接应用于子查询.

解决方法

这里有很好的问题,很多人都遇到过这样的问题,但是懒得停下来看.

你正在做的是在WHERE子句中编写子查询;不是FROM子句中的内联视图.有区别.

在SELECT或WHERE子句中编写子查询时,可以访问主查询的FROM子句中的表.这不仅仅发生在Postgres中,但它是一种标准行为,可以在所有领先的RDBMS中观察到,包括Oracle,sql Server和MysqL.

运行第一个查询时,优化程序会查看整个查询并确定何时检查哪些条件.正是优化器的这种行为,您看到条件延迟到主查询,因为优化器发现在主查询本身中评估此条件而不影响最终结果更快.

如果只运行子查询,注释掉主查询,则必然会在您提到的位置返回错误,因为找不到要引用的列.

在上一段中,您提到已向表tableB添加了一列A2.你观察到的是正确的.这是因为隐含的参考现象.如果未提及列的表别名,则数据库引擎将首先在子查询的FROM子句中的表中查找该列.仅当在那里找不到列时,才会引用主查询中的表.如果您使用以下查询,它仍将返回相同的结果:

Select * from A aa -- Check the alias
Where A1 IN (
    Select distinct B1 from B bb
    Where B2 is something
    And aa.A2 is something -- Check the reference
);

也许您可以在Korth的关于关系数据库的书中找到更多信息,但我不确定.我刚刚根据我的观察回答了你的问题.我知道这发生了,为什么.我只是不知道如何为您提供进一步的参考资料.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...