我正在记录用户观看一系列视频的次数。现在,我正在尝试制作每天观看任何视频的用户数量的图表。
UserVideoWatching.where("created_at >= ? AND user_id != ?",1.month.ago, User.elephant.id).group("DATE(created_at)").reorder('created_at').count
生成sql
SELECT COUNT(*) AS count_all, DATE(created_at) AS date_created_at FROM `user_video_watchings` WHERE (created_at >= '2013-01-27 10:43:24' AND user_id != 7) GROUP BY DATE(created_at) ORDER BY created_at
为每天观看的所有视频产生正确的结果,但正如我所说,我只想向每个用户展示一次。
我想要的SQL是
SELECT COUNT(DISTINCT user_id) AS count_all, DATE(created_at) AS date_created FROM `user_video_watchings` WHERE (created_at >= '2013-01-27 10:33:18' AND user_id != 7) GROUP BY DATE(created_at) ORDER BY created_at
所以我想
UserVideoWatching.where("created_at >= ? AND user_id != ?",1.month.ago, User.elephant.id).group("DATE(created_at)").reorder('created_at').select('COUNT(DISTINCT user_id) AS count_all, DATE(created_at) AS date_created')
会做我想要的。但是这给了
[#<UserVideoWatching >, #<UserVideoWatching >]
而不是哈希。
有什么想法吗?
我正在使用rails 3.1和mysql
答案 0 :(得分:29)
您可以使用distinct.count(:attribute_name)
。
(在Rails 3中使用:count(:user_id, distinct: true)
代替)
因此:
UserVideoWatching.where("created_at >= ? AND user_id != ?", 1.month.ago, User.elephant.id)
.group("DATE(created_at)").reorder('created_at').distinct.count(:user_id)
无法测试,但我认为这会产生你想要的SQL。
答案 1 :(得分:13)
在Rails 4中,使用其他答案中提到的(...).uniq.count(:user_id)
(针对此问题和其他地方的SO)实际上会导致查询中出现额外的DISTINCT
:
SELECT DISTINCT COUNT(DISTINCT user_id) FROM ...
我们实际需要做的是自己使用SQL字符串:
(...).count("DISTINCT user_id")
这给了我们:
SELECT COUNT(DISTINCT user_id) FROM ...
答案 2 :(得分:1)
在rails 5.0.1中应该使用distinct,不同的uniq,但是
[11] pry(main)> Needremember.distinct.count(:word)
(1.1ms) SELECT DISTINCT COUNT(DISTINCT "needremembers"."word") FROM "needremembers"
[12] pry(main)> Needremember.uniq.count(:word)
DEPRECATION WARNING: uniq is deprecated and will be removed from Rails 5.1 (use distinct instead) (called from __pry__ at (pry):12)
(0.6ms) SELECT DISTINCT COUNT(DISTINCT "needremembers"."word") FROM "needremembers"