Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby、Activerecord或Postgresql中按周对活动进行分组和计数_Sql_Ruby On Rails 3_Postgresql_Datetime_Aggregate Functions - Fatal编程技术网

在Ruby、Activerecord或Postgresql中按周对活动进行分组和计数

在Ruby、Activerecord或Postgresql中按周对活动进行分组和计数,sql,ruby-on-rails-3,postgresql,datetime,aggregate-functions,Sql,Ruby On Rails 3,Postgresql,Datetime,Aggregate Functions,我有一个长达几年的活动日志。我被要求计算每个应用程序用户的每周参与度。我将参与定义为用户在任何给定的一周内进行一项或多项记录的活动 我如何对这些活动进行分组,并每周为每个用户统计这些活动?我读过很多不同的帖子,关于arel语法是否是最好的,似乎有争论。我没有超过500个用户,所以性能不是一个问题,而是一个简洁的问题 我成功地尝试了以下方法: user = User.first.activity_logs.group_by { |m| m.created_at.beginning_of_week

我有一个长达几年的活动日志。我被要求计算每个应用程序用户的每周参与度。我将参与定义为用户在任何给定的一周内进行一项或多项记录的活动

我如何对这些活动进行分组,并每周为每个用户统计这些活动?我读过很多不同的帖子,关于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          | 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
这是RubyonRails的模式文件

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;")

这里是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手册中关于提取周()的内容:

日期所在的一年中的周数。根据定义(ISO 8601),一年中的第一周包含该年的1月4日。(ISO-8601周从周一开始。)换句话说,一年中的第一个星期四是该年的第1周。(仅适用于时间戳值)

因此,1月初的日期可能是前一年第52周或第53周的一部分。例如,2005-01-01是2004年第53周的一部分,2006-01-01是2005年第52周的一部分。”

我借用了这个测试并简化了它。活动类型不相关,将每个活动计算为
1

CREATE TEMP TABLE log(usr text, day date);
INSERT INTO log VALUES 
  ('bob' , '2012-01-01')
 ,('bob' , '2012-01-02')
 ,('bob' , '2012-01-14')
 ,('susi', '2012-01-01')
 ,('susi', '2012-01-14');
查询(不会比这更简洁):

结果:

usr  | week     | activity
-----+----------+---------
bob  | 2012-01  | 2
bob  | 2012-02  | 1
susi | 2012-01  | 1
susi | 2012-02  | 1
这很简单。我引述:

WW
一年中的周数(1-53)(第一周从一年的第一天开始。)

我认为:

IW
ISO年度周数(01-53;新年的第一个星期四在第一周。)


演示结果很好,但是为什么不提供表定义和一些示例数据呢?使用的Postgres版本是什么?我可以通过Postgres版本、表定义和一些示例数据来改进这一点。我添加了PG版本和表def。现在这是一个好问题。:)尽管没有向您或@ideamotor提供示例数据或模式,但我还是能够实现这一点。谢谢我在问题的最后使用了最后一个命令。我无法得到你的答案,但这是我的错。我应该给你提供一张样品表。谢谢你的快速回答。
SELECT usr, to_char(day, 'YYYY-WW') AS week, count(*) AS activity
FROM   log
GROUP  BY 1, 2
ORDER  BY 1, 2;
usr  | week     | activity
-----+----------+---------
bob  | 2012-01  | 2
bob  | 2012-02  | 1
susi | 2012-01  | 1
susi | 2012-02  | 1