Рельсы COUNT SELECT DISTINCT
Я записываю, сколько раз пользователи просматривают серию видеороликов. Теперь я пытаюсь составить график количества пользователей, которые каждый день смотрят видео.
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
Ответы
Ответ 1
Вы можете использовать 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, за которым вы после.
Ответ 2
В 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 ...
Ответ 3
Должен использоваться отдельный, в rails 5.0.1, отдельный равный 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"