Подтвердить что ты не робот

Рельсы 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

4b9b3361

Ответ 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"