【问题标题】:count method returns different values depending on date in conditioncount 方法根据条件中的日期返回不同的值
【发布时间】:2017-11-23 10:26:07
【问题描述】:

我正在运行一个查询,该查询使用 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.ago0.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 来计算其他日子......

不确定我在这里遗漏了什么,但希望能帮助您找到问题。

如果您需要更多信息,请告诉我。

【问题讨论】:

  • 你为什么count两次?
  • Jut 更新了问题,以便您可以看到第二个问题的作用,但基本上第二个count 计算返回的哈希数。
  • 我的第一个冲动是你在某处使用 count 但你应该使用 sum。如果您添加原始 MySQL 查询,我可以进一步评论。
  • 刚刚更新了包含原始 SQL 的问题
  • 原始查询是否给您预期的结果?

标签: mysql ruby-on-rails activerecord


【解决方案1】:

您可以使用.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')

【讨论】:

    【解决方案2】:

    首先,您的解决方案不好,因为您需要在 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
    

    然后关于为什么你期望得到 2 时得到 3。Sql COUNT(*) 返回行数。在您的情况下,您将始终拥有 3 个独特的日子,因此 3 个独特的行(group_by 按其独特性对它们进行分组)。您必须像我在查询中所做的那样过滤计数为 0 的天数,以过滤计数为 0 但仍被计数的行

    【讨论】:

      【解决方案3】:

      我找到了一种返回正确结果的方法,但仍然想知道为什么初始查询会返回这些结果。

      这是有效的查询:

      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
      

      【讨论】:

      • IMO,通过添加过滤器以忽略计数为 0 的行,在 SQL 查询中对其进行排序会更有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多