我有一个跨越几年的活动日志。我被要求为应用程序的每个用户计算每周参与度。我将参与度定义为用户在任何给定的一周内进行一个或多个记录的活动。
如何对这些活动进行分组,并按周对每个用户进行计数?我读了很多不同的帖子,关于ruby methods,sql还是arel语法到底是最好的,似乎还存在争论。我没有超过500个用户,所以性能并不是一个重要的问题,而是一个简洁的东西。
我已经成功地尝试过了:
user = User.first.activity_logs.group_by { |m| m.created_at.beginning_of_week }
# => {Mon, 11 Mar 2013 00:00:00 EDT -04:00=>
[#<ActivityLog id: 12345, user_id: 429, ... ]}然后,下一步我可以无错误地返回任何内容:
user.map { |week| week.count } => [2, 2, 2, 2, 2, 2, 2, 2]所以看起来我把事情搞得太复杂了。我如何简洁地计算每周的活动数量,并为每个用户这样做?
我只想要一些我可以最终粘贴到电子表格中的东西(例如,下面),以便为经理制作热图或其他图表。
| User | Week | Activity|
| ------------- | :-------------: | -------:|
| jho | 2013-1 | 20 |
| bmo | 2013-1 | 5 |
| jlo | 2013-1 | 11 |
| gdo | 2013-2 | 2 |
| gdo | 2013-5 | 3 |
| jho | 2013-6 | 5 |编辑
供其他人参考:
Rails 3.1
使用PostgreSQL 9.1.4
以下是ruby on rails中的模式文件
create_table "activity_logs", :force => true do |t|
t.integer "user_id"
t.string "activity_type"
t.datetime "created_at"
t.datetime "updated_at"
end
| ------+| --------+| ----------------+| ----------------+ | ----------------+ |
| id | user_id | activity_type | created_at | updated_at |
| ------+| --------+| ----------------+| ----------------+ | ----------------+ |
| 28257 | 8 | User Signin | 2013-02-14 1... | 2013-02-14 1... |
| 25878 | 7 | Password Res... | 2013-02-03 1... | 2013-02-03 1... |
| 25879 | 7 | User Signin | 2013-02-03 1... | 2013-02-03 1... |
| 25877 | 8 | Password Res... | 2013-02-03 1... | 2013-02-03 1... |
| 19325 | 8 | Created report | 2012-12-16 0... | 2012-12-16 0... |
| 19324 | 9 | Added product | 2012-12-16 0... | 2012-12-16 0... |
| 18702 | 8 | Added event | 2012-12-15 1... | 2012-12-15 1... |
| 18701 | 1 | Birthday Email | 2012-12-15 0... | 2012-12-15 0... |
| ------+| --------+| ----------------+| ----------------+ | ----------------+ | 解决方案
修改@Erwin Brandstetter的命令,我在命令行上得到了想要的结果:
ActivityLogs.find_by_sql("
SELECT user_id, to_char(created_at, 'YYYY-WW') AS week, count(*) AS activity
FROM activity_logs
GROUP BY 1, 2
ORDER BY 1, 2;")发布于 2013-03-22 08:54:00
这里是Postgresql。这里的诀窍是你需要生成你的年周值。在这里,我从日期中提取信息并将其连接起来。
在这里,我保证'2012-01-01‘不会被算作52周。我凌驾于标准之上。根据定义周的方式,您可能需要更改此函数。
create temp table daily_log(person character varying, activity numeric,
dayof date);
insert into daily_log values
('bob' ,1,'2012-01-01')
,('bob' ,1,'2012-01-02')
,('bob' ,0,'2012-01-14')
,('charlie',1,'2012-01-01')
,('charlie',1,'2012-01-14')
select person
,extract('year' from dayof) || '-' ||
case when extract('week' FROM dayof) >= 52
and extract('month' FROM dayof) = 1
then 1
else extract('week' FROM dayof) end as weekof
,sum(activity) as activity_cnt
from daily_log
group by weekof, person
order by person, weekof;这将为您带来:
| person | weekof | activity_cnt|
| -------------:| :--------------:| -----------:|
| bob | 2012-1 | 2 |
| bob | 2012-2 | 0 |
| charlie | 2012-1 | 1 |
| charlie | 2012-2 | 1 |为什么我用2012,我不知道。
下面是postgresl手册中关于提取周(http://www.postgresql.org/docs/9.2/static/functions-datetime.html)的说明:
“一天所在的一年中的第几个星期。根据定义(ISO 8601),一年的第一周包含该年的1月4日。( ISO-8601一周从星期一开始。)换句话说,一年的第一个星期四在该年的第一周。(仅用于时间戳值)
因此,一月初的日期可能是前一年的52周或53周的一部分。例如,2005-01-01是2004年53周的一部分,2006-01-01是2005年52周的一部分。“
https://stackoverflow.com/questions/15554246
复制相似问题