使用 WHERE 子句中的 null 和 false 检查优化查询

Optimize query with null and false checks in WHERE clause

提问人:Samra 提问时间:10/24/2022 最后编辑:Erwin BrandstetterSamra 更新时间:10/24/2022 访问量:128

问:

我可以使以下查询更短和/或最佳吗?

WITH myvars (t_state, t_hv_involved, num_vehicle_hv )
AS (VALUES ('TAS', null, null))

SELECT * FROM safety.crash_summary_view c, myvars 
WHERE jurisdiction = t_state
AND ((t_hv_involved::boolean = TRUE AND c.num_vehicle_hv > 0)
   OR t_hv_involved is null
   OR t_hv_involved::boolean = FALSE)

如果是,那么它应该过滤 .
如果为 或 ,则不进行筛选。
t_hv_involvedtruenum_vehicle_hv > 0t_hv_involvedfalsenull

SQL PostgreSQL 类型 查询优化 布尔逻辑

评论

0赞 Deepstop 10/24/2022
你可以通过省略并更改为 来缩短它,但我认为这不是你所追求的。= TRUEt_hv_involved::boolean = FALSENOT t_hv_involved::boolean

答:

1赞 Erwin Brandstetter 10/24/2022 #1
...
AND   (t_hv_involved IS NOT TRUE OR c.num_vehicle_hv > 0)

假设类型应有,则无需强制转换。t_hv_involvedboolean

手册:

boolean IS NOT TRUEboolean

测试布尔表达式是否生成 false 或 unknown。

→(而不是
true IS NOT TRUEfNULL::boolean IS NOT TRUEtNULL)

完整的测试用例可以是:

SELECT *  -- you really need all columns?
FROM   safety.crash_summary_view c
CROSS  JOIN (
   VALUES
     ('TAS', null::bool, null::numeric)
   ) v (t_state, t_hv_involved, num_vehicle_hv)
WHERE  c.jurisdiction = v.t_state
AND   (v.t_hv_involved IS NOT TRUE OR c.num_vehicle_hv > 0);

请注意表达式第一行中的显式类型声明。无论如何,我没有强制转换,因为默认要输入。你可能也想明确一点,并投射出来。
其他行可以是非类型化的文本,但不能用引号括起来。
看:
VALUES'TAS'textboolean

当然,是当你通过 时,测试不返回任何带有 的行。c.num_vehicle_hv > 0nullnullnum_vehicle_hvv.t_hv_involved IS TRUE

评论

0赞 Laurenz Albe 10/24/2022
也许你应该推荐一个条件索引。