我有以下数据库结构:
| ID | Title |
|----|----------------|
| 1 | Taggable title |
| id | taggable_id | taggable_type | tag_id | created_at |
|----|-------------|---------------|--------|---------------------|
| 1 | 1 | Taggable | 100 | 2018-01-01 09:00:00 |
| id | name |
|----|-----------|
|100 | First tag |
我需要确定其中哪一个"标签"最近趋势。第一个挑战是发明一些简单的算法来计算什么"趋势"手段。我决定使用最简单的一个(这不是什么大问题,以后可以进行微调),这可能有点蹩脚但是有效 - 计算每个标签在过去一小时和3小时前有多少个标签,计算当前计数和旧计数之间的差异,并按该差异对结果进行排序。
我当前对此的SQL查询如下:
select DISTINCT(tags.id), tags.*, (
select COUNT(*)
from taggings
where taggings.tag_id = tags.id
and taggings.created_at::timestamp > now() - interval '3 hour'
) - (
select COUNT(*)
from taggings
where taggings.tag_id = gutentag_tags.id
and taggings.created_at <= now()::timestamp - interval '3 hour'
and taggings.created_at > now()::timestamp - interval '12 hour'
) as hottness
from tags
left join taggings on tags.id = taggings.tag_id
where taggings.created_at >= now()::timestamp - interval '12 hours'
order by hottness desc
准备使用的sqlfiddle在这里: http://sqlfiddle.com/#!17/2298a/1
而且我非常确定它完全糟糕且不够理想,它会在更高负载下杀死我的服务器 - 但它确实有效。有没有人知道我怎么能改进它,或者我怎样才能完全改变我的尝试,让它更好更安全?提前谢谢。
答案 0 :(得分:0)
只需查询一次标记就可以优化
select tags.id,
count( case when taggings.created_at::timestamp > now() - interval '3 hour' then 1 else null end
)
-
count ( case when
taggings.created_at <= now()::timestamp - interval '3 hour'
and taggings.created_at > now()::timestamp - interval '12 hour'
then 1 else null end
) as hottness
from tags
left join taggings on tags.id = taggings.tag_id
where taggings.created_at >= now()::timestamp - interval '12 hours'
group by tags.id
order by hottness desc