如何在SQL(Postgres)中强制筛选求值顺序?
我有一张表,简化后大致如下:如何在SQL(Postgres)中强制筛选求值顺序?,sql,postgresql,Sql,Postgresql,我有一张表,简化后大致如下: id | type | header | body =========================================== 1 | A | {type: A} | {content: "Hi"} 2 | A | {type: A} | {content: "Hello"} 3 | B | {type: B} | ["Hi","Hello"] 以下查询提供了一个错误: > select * from Table w
id | type | header | body
===========================================
1 | A | {type: A} | {content: "Hi"}
2 | A | {type: A} | {content: "Hello"}
3 | B | {type: B} | ["Hi","Hello"]
以下查询提供了一个错误:
> select * from Table where header->>'type'='A' and body->>'content' like 'H%'
ERROR: cannot extract field from a non-object
这很公平,但这个问题也是如此:
> select * from (select * from Table where header->>'type'='A') where body->>'content' like 'H%'
鉴于这些不包括:
> select * from Table where type='A' and body->>'content' like 'H%'
> select * from Table where header->>'type'='A' and body->>'content'='Hello'
对于这种特定的情况(like谓词被错误地赋予了优先权),我有解决办法,但我担心的是,我甚至不能依靠括号来控制计算顺序,即使在这种情况下,它改变了应用于数据的约束。有什么常规方法可以做到这一点吗?您应该能够使用
案例
强制执行评估顺序:
select *
from Table
where (case when header->>'type'='A'
then (case when body->>'content' like 'H%' then 1 end)
end) = 1;
这大概是我唯一一次建议将case
语句放在where
子句中
您还可以使用CTE保证订单:
with t as (
select t.*
from table t
where header->>'type'='A'
)
select t.*
from t
where body->>'content' like 'H%';
但是,这会带来实现中间结果的额外开销。(这是补充信息;Gordon的答案应该标记为正确)
在SQL中,DB可以任意顺序执行谓词。没有短路。括号内的组覆盖默认运算符优先级,以控制哪些运算符绑定到哪些操作数,但不强制执行顺序
子查询不能保证执行顺序。在可能的情况下,可以并且应该通过将其展平到外部查询来优化它
您遇到的问题与处理被零除的问题相同,并且具有相同的解决方案
正确的解决方案是使用
CASE
强制执行顺序,如Gordon所示。您可以使用CTE(带
)或偏移量0
破解,但两者都会影响性能。太棒了,谢谢。我没有意识到CTE的计算与嵌套查询不同——我认为它们主要是为了避免名称空间污染。很高兴知道。