这是我要问的问题,
SELECT s.id, s.name AS name,
CASE WHEN (ARRAY_AGG(tgs.status) @> '{Hard} ') THEN 'Hard'
WHEN (ARRAY_AGG(tgs.status) @> '{Soft} ') THEN 'Soft'
WHEN (ARRAY_AGG(tgs.status) @> '{Fluid} ') THEN 'Fluid'
WHEN (ARRAY_AGG(tgs.status) @> '{Gummy} ') THEN 'Gummy'
WHEN (ARRAY_AGG(tgs.status) @> '{Expired} ') THEN 'Expired'
END AS status,
COUNT(*) OVER()
FROM sweets AS s
INNER JOIN tasty_goofy_sweets AS tgs on tgs.sweet_id = s.id
GROUP BY s.id;
在实现这一点时,我的朋友建议,我们可以使用left join-lateral并只计算一次,而不是在switch情况下每次都计算array\u agg。i、 e)实施如下
SELECT s.id, s.name AS name,
CASE WHEN (tgs.status @> '{Hard} ') THEN 'Hard'
WHEN (tgs.arr_status @> '{Soft} ') THEN 'Soft'
WHEN (tgs.arr_status @> '{Fluid} ') THEN 'Fluid'
WHEN (tgs.arr_status @> '{Gummy} ') THEN 'Gummy'
WHEN (tgs.arr_status @> '{Expired} ') THEN 'Expired'
END AS status,
COUNT(*) OVER()
FROM sweets AS s
LEFT JOIN LATERAL ( SELECT ARRAY_AGG(tgs.status) AS arr_status FROM tasty_goofy_sweets tgs WHERE tgs.sweet_id = s.id
) AS tgs ON TRUE
GROUP BY s.id;
但我不确定postgres是否计算 ARRAY_AGG
珍惜每一次,我们如何才能决定哪种方法更好?我试着看着 explain analyse
对于这两个查询,后一个查询中涉及的行数都多于前者。但我不明白为什么会这样?
我直觉上觉得前一种方法更好,但有人能解释一下,哪种更好,为什么我要求太多?
2条答案
按热度按时间f1tvaqid1#
我很肯定在一个
case
表达式when
对于每个条件,子句将分别进行评估。这意味着你的同事是对的。可能。文件的有效部分是:
每个条件都是一个返回布尔结果的表达式。如果条件的结果为true,则case表达式的值是该条件后面的结果,并且不处理case表达式的其余部分。
postgres有可能通过对子表达式求值一次来对其进行某种优化。然而,“case表达式的剩余部分未被处理”这句话非常有力,它表明每个子句只有在前一个子句的计算结果为false(或false)之后才会被处理
NULL
).不管优化器是否发现一个函数只能被调用一次,横向连接保证它只被求值一次,所以对于一个昂贵的操作来说,这似乎是更安全的解决方案。
tnkciper2#
最有可能的是,postgres会优化掉这个倍数
array_agg()
s、 只计算一次,并在每次比较中重用结果。这是非常简单的查询优化,数据库应该很容易发现。不过,我建议您使用条件聚合来简化查询。您不需要聚合到一个数组中,只是为了检查给定的值是否存在:
您也可以使用横向联接和条件排序来表示此表达式,而无需聚合: