我正在运行一个查询,该查询查看数据库中过去三天(今天包括)中记录活动的天数,使用GroupBy gem按天分组。以下是完整查询:
Record.activities.where("created_at >= ?", 2.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count.count
2天前,我有1个活动,昨天我有0个,今天我有2个。这应该返回2个(不是3个,它计算的日子不是活动)但是由于某种原因它会返回3.更奇怪的是如果我将2.days.ago
更改为1.day.ago
或0.days.ago
,则会返回正确的值,1。它会忽略昨天没有活动的地方,只计算它在那里识别的那一天(今天)是一项活动。
如果我删除了第二个.count
,则返回2.days.ago
的内容...
{Tue, 21 Nov 2017=>1, Wed, 22 Nov 2017=>0, Thu, 23 Nov 2017=>2}
如果我为1.day.ago
运行它,我会......
{Thu, 23 Nov 2017=>2}
以下是2.days.ago
查询的原始SQL ..
SELECT COUNT(*) AS count_all, strftime('%Y-%m-%d 00:00:00 UTC', created_at)
AS strftime_y_m_d_00_00_00_utc_created_at
FROM "activities"
WHERE "activities"."goal_id" = ? AND (created_at >= '2017-11-21 00:00:00')
AND (created_at IS NOT NULL)
GROUP BY strftime('%Y-%m-%d 00:00:00 UTC', created_at)
经过一些更多的测试,我发现如果x.days.ago
中的x落在0的那一天,它只会忽略一天有0个活动。如果有0个活动超过1天,它将忽略第一个一个应该的,但然后计算其他几天0后来......
不确定我在这里缺少什么,但感谢任何帮助找到问题。
如果您需要更多信息,请与我们联系。
答案 0 :(得分:2)
您可以使用.having('count(activities.id) > 0')
忽略没有活动的天数
下面未经测试的查询:
Record.activities
.select('count(activities.id) as count_all,date(activities.created_at) as day')
.where("created_at >= ?", 2.days.ago.beginning_of_day.in_time_zone)
.group('day').having('count_all > 0')
答案 1 :(得分:0)
我找到了一种方法来返回正确的结果,但仍然很想知道为什么初始查询会返回这些结果。
以下是有效的查询:
Record.activities.where("created_at >= ?", 4.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count.reject {|k,v| v == 0 }.count
答案 2 :(得分:0)
首先你的解决方案是不行的,因为你需要在sql查询中进行它(当你将所有数据加载到ruby对象然后对它们进行排序。它将在规模期间成为瓶颈)。把同样的东西放到sql上。我认为这个应该有效:
Record.activities.where("created_at >= ? AND count_all > 0", 2.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count
然后了解为什么在期望得到3时得到3的原因.Sql COUNT(*)
返回行数。在您的情况下,您将始终有3个独特的日期,因此3个唯一的行(group_by按其唯一性对它们进行分组)。您必须按我在查询中的0次计算过滤天数,以过滤行数,但计数为0,但仍会计算