Sql where子句中的非相关exists(…)查询是针对每行执行还是仅执行一次?
我有以下疑问:Sql where子句中的非相关exists(…)查询是针对每行执行还是仅执行一次?,sql,postgresql,correlated-subquery,Sql,Postgresql,Correlated Subquery,我有以下疑问: SELECT * FROM t1, t2 WHERE t1.some_id = t2.some_id and not exists(select true from some_table where some_column = true) 此处,not exists从某个表中选择true,其中。。。不从主查询中引用t1或t2 这是否不存在从某个表中选择true,其中。。。只执行一次,或者对t1和t2之间的乘积的每个元组执行一次,其中t1.som
SELECT *
FROM t1, t2
WHERE t1.some_id = t2.some_id
and
not exists(select true from some_table where some_column = true)
此处,not exists从某个表中选择true,其中。。。不从主查询中引用t1或t2
这是否不存在从某个表中选择true,其中。。。只执行一次,或者对t1和t2之间的乘积的每个元组执行一次,其中t1.some_id=t2.some_id为真
换句话说,如果只执行一次,如果结果为false,则可以立即返回空表。逻辑上,我们写了:
if (not exists(select true from some_table where some_column = true))
SELECT *
FROM t1, t2
WHERE t1.some_id = t2.some_id
else
empty table
首先,学习使用正确的连接语法: 子查询只能执行一次。然而,这最终取决于Postgres优化器。您可以保证使用左联接只执行一次代码:
您甚至可以将EXISTS条件包装到纯SQL函数中,并且只执行一次: 如果将关键字STABLE添加到函数定义中,DBMS将知道返回值不会在同一事务/语句中更改。如果没有STABLE,函数将为每行调用一次 稳定函数的结果是一个一次性过滤器: 4排 与不相关子查询相同的条件基本上产生与稳定函数相同的计划现在子查询执行一次,其结果$0在一次性过滤器中测试: 但是,我们是否仍然在扫描表,如果该函数返回false,我们就为每一行执行where false,如果该函数返回true,我们就为每一行执行where true
从未执行说明一切。注意:SQL中没有IF,plpgsql中也没有IF。并且:EXISTS子查询只执行一次,即使不相关,也要检查计划!如果子查询是相关的,它将是连接计划的一部分。我知道SQL中没有If。我是说我们正在模拟一个if。像这样模拟if是个好主意吗?像这样模拟if是在纯SQL中实现的唯一方法。我的意思是:我们可以这样做,或者我们可以编写一个plpgsql函数来表达一个真正的if。你喜欢哪种方法?谢谢。您能解释一下为什么左连接强制planner只执行一次查询,而where子句中的not不存在是不确定的吗?不过,我已经知道了连接语法,谢谢。我主要关注的是子查询。没有区别,左连接。。。为空且不存在。。。两者都产生了一个反加入计划。唯一的区别是t2.*列在外部查询中变得可见。我仍然没有100%的遵循。唯一不同的是,t2.*列在外部查询中变为可见。?@CarolineKwerts。这意味着如果您使用select*,您也将从该表中获取列。谢谢。然后,我仍然很困惑你为什么说用左键连接。。。如果为NULL,我们保证查询将只执行一次,但不使用简单的not EXISTS。为什么会这样?当执行最后一个查询时,从omg中选择*其中欠钱,计划者给出:omg成本上的顺序扫描=0.00..597.60行=753宽度=8过滤器:欠钱。那么这不意味着它将对每一行执行吗?稳定关键字,明白了。函数现在执行一次,因此查询执行一次。但是,我们是否仍然在扫描表,如果该函数返回false,则对每行执行where false,如果该函数返回true,则执行where true?谢谢,非常有见地!
SELECT *
FROM t1 JOIN
t2
ON t1.some_id = t2.some_id
WHERE not exists(select true from some_table where some_column = true);
SELECT t1.*, t2.*
FROM t1 JOIN
t2
ON t1.some_id = t2.some_id LEFT JOIN
some_table st
ON st.some_column = true
WHERE st.some_column IS NULL;
-- \i tmp.sql
CREATE TABLE omg
( id integer NOT NULL PRIMARY KEY
, must_pay integer NOT NULL
);
INSERT INTO omg(id, must_pay) VALUES(1,0);
CREATE FUNCTION owe_money() RETURNS BOOLEAN AS
$func$
SELECT EXISTS(SELECT 1
FROM omg o
WHERE o.must_pay > 0
);
$func$
-- language sql;
language sql STABLE;
EXPLAIN
SELECT owe_money();
INSERT INTO omg(id, must_pay) VALUES(2,100);
EXPLAIN
SELECT owe_money();
EXPLAIN
SELECT * FROM omg
WHERE owe_money();
QUERY PLAN
-------------------------------------------------------------------------------------------------
Seq Scan on omg (cost=0.00..566.40 rows=713 width=8) (actual time=0.303..0.331 rows=2 loops=1)
Filter: owe_money()
Total runtime: 0.384 ms
(3 rows)
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Result (cost=0.25..31.65 rows=2140 width=8) (actual time=0.304..0.316 rows=2 loops=1)
One-Time Filter: owe_money()
-> Seq Scan on omg (cost=0.25..31.65 rows=2140 width=8) (actual time=0.004..0.009 rows=2 loops=1)
Total runtime: 0.379 ms
EXPLAIN ANALYZE
SELECT * FROM omg
WHERE EXISTS (
SELECT 1
FROM omg o
WHERE o.must_pay > 0
);
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Result (cost=0.05..31.45 rows=2140 width=8) (actual time=0.022..0.034 rows=2 loops=1)
One-Time Filter: $0
InitPlan 1 (returns $0)
-> Seq Scan on omg o (cost=0.00..36.75 rows=713 width=0) (actual time=0.011..0.011 rows=1 loops=1)
Filter: (must_pay > 0)
Rows Removed by Filter: 1
-> Seq Scan on omg (cost=0.00..31.40 rows=2140 width=8) (actual time=0.003..0.008 rows=2 loops=1)
Total runtime: 0.081 ms
(8 rows)
EXPLAIN ANALYZE
SELECT * FROM omg
WHERE EXISTS (
SELECT 1
FROM omg o
WHERE o.id < 0
);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=1.66..3.66 rows=100 width=8) (actual time=0.011..0.011 rows=0 loops=1)
One-Time Filter: $0
InitPlan 1 (returns $0)
-> Index Only Scan using omg_pkey on omg o (cost=0.14..1.66 rows=1 width=0) (actual time=0.006..0.006 rows=0 loops=1)
Index Cond: (id < 0)
Heap Fetches: 0
-> Seq Scan on omg (cost=0.00..2.00 rows=100 width=8) (never executed)
Total runtime: 0.063 ms
(8 rows)