0

给定以下模型:

User
    id
UserPulses
    id, user_id, group_id, created_at

我想做的是获取按(group_id)分组的所有用户的UserPulse,并且只获取每个group_id 的最新UserPulse。我已经能够通过逐组循环来做到这一点,但这需要大量查询。这可以通过一个查询来实现吗?

类似于:user.user_pulses.group("group_id)")

有任何想法吗?谢谢

4

3 回答 3

2

您不能通过通常的 ActiveRecord 接口可靠地执行此操作,但您可以使用窗口函数通过 SQL 执行此操作。你想要一些这样的 SQL:

select id, user_id, group_id, created_at
from (
    select id, user_id, group_id, created_at, 
           row_number() over (partition by group_id order by created_at desc, id desc) as r
    from user_pulses
    where user_id = :user_id
) dt
where r = 1

然后将其包装在find_by_sql

pulses = UserPulses.find_by_sql([%q{
    select id, user_id, group_id, created_at
    from (
        select id, user_id, group_id, created_at, 
               row_number() over (partition by group_id order by created_at desc, id desc) as r
        from user_pulses
        where user_id = :user_id
    ) dt
    where r = 1
}, :user_id => user.id])

窗口函数部分本质上对每个 GROUP BY 执行本地 GROUP BY ,对group_id它们进行排序(id desc作为辅助排序键作为“以防万一”的决胜局),并将每组的行号添加到r. 然后外部查询过滤掉每个组 ( where r = 1) and peels off the originaluser_pulses 列中的第一个。

于 2012-08-22T02:36:07.333 回答
2

您可以使用 SQL 特性的 PostgreSQL 特定扩展DISTINCTDISTINCT ON

SELECT DISTINCT ON (group_id)
       id, user_id, group_id, created_at
FROM   user_pulses
WHERE  user_id = :user_id
ORDER  BY group_id, created_at DESC, id; -- id just to break ties

比窗口函数更简单(但不那么便携)并且可能最快。此相关问题下的
更多详细信息。

于 2012-08-22T18:15:03.647 回答
0

可能是这样的。但是,如果用户/组 ID 组合的日期相同,则它们可能有多个记录。

SELECT p.id, p.user_id, p.group_id, p.created_at
  FROM UserPulses p
      ,( SELECT user_id, group_id, MAX(created_at) as max_date
           FROM UserPulses
           GROUP BY user_id, group_id ) m
  WHERE u.user_id = m.user_id
    AND u.group_id = m.group_id
    AND u.created_at = m.max_date
于 2012-08-22T01:51:57.877 回答