[英]How to query for records based on a group and ordering?
給定以下模型:
User
id
UserPulses
id, user_id, group_id, created_at
我想做的是獲取按(group_id)分組的所有用戶UserPulses,並且僅按group_id獲取最新的UserPulse。 我已經能夠通過逐組循環來做到這一點,但這需要大量的查詢。 一個查詢可能嗎?
類似於:user.user_pulses.group(“ group_id)”)
有任何想法嗎? 謝謝
您無法通過常規的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_id
進行本地GROUP BY,對它們group_id
排序(將id desc
作為輔助排序鍵作為“以防萬一”的平局決勝者),並在r
每個組的行號。 然后外部查詢過濾掉每個組中的第一個查詢( where r = 1
), and peels off the original
user_pulses`列。
您可以使用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
大概是這樣的。 但是,如果一個用戶/ 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.