鉴于以下模型:
User
id
UserPulses
id, user_id, group_id, created_at
我想要做的是获取按(group_id)分组的所有用户的UserPulses,并且每个group_id仅获取最新的UserPulse。我已经能够通过逐个循环遍历这样做,但这需要大量的查询。这可以用一个查询吗?
像: user.user_pulses.group( “GROUP_ID)”)
有什么想法吗?感谢
答案 0 :(得分:2)
您不能通过通常的ActiveRecord接口可靠地执行此操作,但您可以使用window function通过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_id
执行本地GROUP BY,对它们进行排序(使用id desc
作为辅助排序键作为“以防万一”绑定断路器),并对每个进行排序 - r
中的组行号。然后外部查询过滤掉每个组中的第一个(where r = 1
)and peels off the original
user_pulses`列。
答案 1 :(得分:2)
您可以使用SQL功能DISTINCT
的PostgreSQL特定扩展:DISTINCT 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
比窗口功能更简单(但不是便携式),可能最快 更多details under this related question。
答案 2 :(得分:0)
也许是这样的。但如果用户/ group_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