如果我有一个查询
SELECT date_trunc('day', assigndate)e,
count(CASE WHEN a.assigneeid = 65548
AND a.assigneeid IN
(SELECT userid
FROM groupmembers
WHERE groupid = 65553) THEN 1 ELSE NULL END) assigned,
count(CASE WHEN a.assigneeid = 65548
AND a.completedtime IS NOT NULL
AND a.assigneeid IN
(SELECT userid
FROM groupmembers
WHERE groupid = 65553) THEN 1 ELSE NULL END) completed
FROM ASSIGNMENT a
WHERE assigndate > CURRENT_TIMESTAMP - interval '20 days'
GROUP BY date_trunc('day',assigndate);
有问题的子查询是
SELECT userid
FROM groupmembers
WHERE groupid = 65553
然后,由于子查询为父级查询的not co-related
,因此将仅执行一次,并且将使用缓存结果。但是,由于该子查询存在于查询中的两个位置,然后根据SQL plan
,因此对其进行评估两次。有什么方法可以cache
该子查询的结果并在两个位置使用?
不能将子查询转换为加入,因为没有任何一个字段可以加入(这不是无条件的加入,因为计数将会成为错误)
您可以使用公共表Express(WITH
)
with cte as
(
SELECT userid FROM groupmembers WHERE groupid = 65553
)
SELECT
date_trunc('day', assigndate)e,
count(CASE WHEN a.assigneeid = 65548 AND a.assigneeid IN
(SELECT userid from cte) then 1 else null end) assigned,
...
您应该重写查询以消除子查询:
SELECT date_trunc('day', assigndate)e,
sum(CASE WHEN a.assigneeid = 65548 and gm.userid is not null then 1 else 0
end) as assigned,
sum(CASE WHEN a.assigneeid = 65548 and a.completedtime IS NOT NULL and gm.userid is not null
then 1 else 0
end) as completed
FROM ASSIGNMENT a left outer join
(select distinct userid
from groupmembers
where groupid = 65553
) gm
on a.assigneeid = gm.userid
WHERE assigndate > CURRENT_TIMESTAMP - interval '20 days'
GROUP BY date_trunc('day',assigndate)
order by 1
通常,我认为将表参考保留在FROM
(或WITH
)子句中是一个好习惯。很难遵循SELECT
子句中的子查询的逻辑。在这种情况下,子征服是如此的节日,以至于它们实际上乞求将其合并到一个语句中。