限制在组 - ActiveRecord Postgres

时间:2014-09-15 17:56:49

标签: sql ruby-on-rails postgresql activerecord postgresql-9.3

我有一个事件表我按月查询并尝试将每天返回的事件数量限制为3.

[39] pry(#<EventsController>)> @events.group("DATE_TRUNC('day', start)").count

CACHE (0.0ms)  SELECT COUNT(*) AS count_all, DATE_TRUNC('day', start) AS
date_trunc_day_start FROM "events"  WHERE ((start >= '2014-08-31 00:00:00' and
start <= '2014-    10-12 00:00:00'))  GROUP BY DATE_TRUNC('day', start)
=> {2014-09-24 00:00:00 UTC=>5,
 2014-09-18 00:00:00 UTC=>6,
 2014-09-25 00:00:00 UTC=>3}

这里我们24日有5场比赛,18日有6场,25日有3场。 http://stackoverflow.com/a/12529783/3317093>

当我尝试没有.count的查询时,我收到错误消息

PG::GroupingError: ERROR:  column "events.id" must appear in the GROUP BY clause or be used in an aggregate function

我查看了使用select()来使分组工作,但是需要列出表中的所有列。我应该如何构造查询/范围以从每组事件中返回3条记录?

编辑 - 我关闭了! 我发现了许多类似的问题,其中大多数是在使用select的MySQL中。我认为使用select可以成为一种方式,可以是事件。*或者如下所示

@events.where("exists (select 1 from events GROUP BY DATE_TRUNC('day', start) limit 3)")

产生SQL

SELECT "events".* FROM "events"  WHERE ((start >= '2014-08-31 00:00:00'
and start <= '2014-10-12 00:00:00')) AND (exists (select 1 from events
GROUP BY DATE_TRUNC('day', start) limit 3))

查询返回按id排序的所有@events(似乎:id隐含地是分组的一部分)。我尝试过切换,但通常会遇到与之前相同的分组错误。

2 个答案:

答案 0 :(得分:0)

如果您不想使用count,可以使用rails中的group_by列出事件,如下所示:

hash = @events.group_by{ |p| p.start.to_date}

并将此代码用于每个日期的限制(3):

hash.inject({}){ |hash, (k, v)| hash.merge( k => v.take(3) )  }

Helper link用于哈希映射,并返回哈希而不是数组。

答案 1 :(得分:0)

对于遇到类似问题的任何人,我建议您查看window functionsthis blog post covering different ways to solve a similar question。帖子中涉及的三种方法包括使用1)group_by,2)SQL子选择,3)窗口函数。

我的解决方案,使用窗口函数:

@events.where("(events.id)
  IN (
    SELECT id FROM
      ( SELECT DISTINCT id,
                        row_number() OVER (PARTITION BY DATE_TRUNC('day', start) ORDER BY id) AS rank 
      FROM events) AS result
    WHERE (
      start >= '#{startt}' and
      start <= '#{endt}' and
      rank <= 3
    )
  )
")