您无法通过通常的 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 originaluser_pulses` 列。