ADT*_*DTC 8 sql postgresql subquery in-subquery postgresql-9.1
假设有两个表:
Table A: A1, A2, A_Other
Table B: B1, B2, B_Other
Run Code Online (Sandbox Code Playgroud)
在以下示例中, is something 是针对固定值检查的条件,例如 = 'ABC' 或 < 45.
我写了一个如下(1)的查询:
Select * from A
Where A1 IN (
Select Distinct B1 from B
Where B2 is something
And A2 is something
);
Run Code Online (Sandbox Code Playgroud)
我真正想写的是(2):
Select * from A
Where A1 IN (
Select Distinct B1 from B
Where B2 is something
)
And A2 is something;
Run Code Online (Sandbox Code Playgroud)
奇怪的是,两个查询都返回了相同的结果.在查看查询1的解释计划时,看起来就像执行子查询时一样,因为条件不适用于子查询,所以它被推迟用作主查询结果的过滤器.A2 is something
我通常希望查询1失败,因为子查询本身会失败:
Select Distinct B1 from B
Where B2 is something
And A2 is something; --- ERROR: column "A2" does not exist
Run Code Online (Sandbox Code Playgroud)
但我发现情况并非如此,Postgres将不适用的子查询条件推迟到主查询.
这是标准行为还是Postgres异常?这在哪里记录,这个功能叫做什么?
此外,我发现如果我A2在表中添加一列B,则只有查询2按预期工作.在这种情况下A2,查询2中的引用仍将引用A.A2,但查询1中的引用将引用新列,B.A2因为它现在可直接应用于子查询.
这里有一个很好的问题,很多人遇到的东西,但是懒得停下来看.
你正在做的是在WHERE子句中写一个子查询; 不是该FROM条款中的内联视图.有区别.
在子查询SELECT或WHERE子句中编写子查询时,可以访问FROM主查询子句中的表.这不仅仅发生在Postgres中,但它是一种标准行为,可以在所有领先的RDBMS中观察到,包括Oracle,SQL Server和MySQL.
运行第一个查询时,优化程序会查看整个查询并确定何时检查哪些条件.正是优化器的这种行为,您看到条件延迟到主查询,因为优化器发现在主查询本身中评估此条件而不影响最终结果更快.
如果只运行子查询,注释掉主查询,则必然会在您提到的位置返回错误,因为找不到要引用的列.
在最后一段中,您提到已向A2表中添加了一列tableB.你观察到的是对的.这是因为隐含的参考现象.如果未提及列的表别名,则数据库引擎将首先在FROM子查询的tables in 子句中查找该列.仅当在那里找不到列时,才会引用主查询中的表.如果您使用以下查询,它仍将返回相同的结果:
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
);
Run Code Online (Sandbox Code Playgroud)
也许您可以在Korth的关于关系数据库的书中找到更多信息,但我不确定.我刚刚根据我的观察回答了你的问题.我知道这发生了,为什么.我只是不知道如何为您提供进一步的参考资料.