目标-第1天的滚动保留百分比
问题:
1)我如何加快此查询的速度?
2)这种与数字的对话会减慢查询速度?
3)我是否还有其他选择可以将round()换成其他方式?还是最佳?
查询:
SELECT date(reg_time), round(CAST(count(DISTINCT du.uid) / count(DISTINCT users.uid)::float * 100 AS numeric), 2) AS rolling_retention_day1
FROM users
LEFT JOIN dailyusers du
ON users.uid = du.uid
AND date(reg_time) BETWEEN current_date - interval '30' DAY AND current_date
AND date(reg_time) + 1 <= day
GROUP BY date(reg_time);
答案 0 :(得分:0)
reg_time
包含在日期功能中。
如果reg_time
是索引列,则用日期功能将reg_time括起来会中断索引搜索。您需要考虑不要使用date(reg_time)
您还可以使用SQL Explain Plan
答案 1 :(得分:0)
使用正确的索引,我怀疑这会更快:
SELECT reg_date, AVG(du_flag) as rolling_retention_day1
FROM (SELECT date(u.reg_time) as reg_date,
(CASE WHEN EXISTS (SELECT 1
FROM dailyusers du
WHERE du.uid = u.uid AND
date(u.reg_time) + 1 <= du.day
)
THEN 1 ELSE 0
END) as du_flag
FROM users u
WHERE u.reg_time >= current_date - interval '30' day AND
u.reg_time < current_date + interval '1' day
)
GROUP BY reg_date;
您要在users(reg_time)
和dailyusers(uid, day)
上建立索引。假设uid
在users
中是唯一的,这对我来说很有意义。
如果您真的很关心平均值的格式,则可以:
AVG(du_flag)::decimal(4, 2)
这是我对您给出的查询所能做的最好的事情。可能有更好的方式编写查询。如果您需要帮助,我建议您问另一个问题,并提供示例数据,所需结果以及对查询正在执行(或应该执行)的解释。