[英]Order with DISTINCT ids in rails with postgres
我有以下代碼用micropost_id列連接兩個表微博和活動,然后根據具有不同微博id的活動表的created_at進行排序。
Micropost.joins("INNER JOIN activities ON
(activities.micropost_id = microposts.id)").
where('activities.user_id= ?',id).order('activities.created_at DESC').
select("DISTINCT (microposts.id), *")
這應該返回整個微柱。這在我的開發環境中不起作用。
(PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
如果我在SELECT DISTINCT中添加activities.created_at,我會得到重復的微博ID,因為它有不同的activities.created_at列。 我已經做了很多搜索到達這里。 但是由於這種postgres條件,問題總是存在,以避免隨機選擇。
我想根據activities.created_at的順序選擇不同的micropost _id。
請幫忙..
首先,我們需要快速介紹SELECT DISTINCT
實際執行的操作。 它看起來只是一個很好的關鍵字,以確保您只返回不同的值,這不應該改變任何東西,對嗎? 除了你在幕后發現, SELECT DISTINCT
實際上更像是一個GROUP BY
。 如果要選擇某些事物的不同值,則只能按照您選擇的相同值對該結果集進行排序 - 否則,Postgres不知道該怎么做。
要解釋模糊性的來源,請考慮您的activities
這一組簡單數據:
CREATE TABLE activities (
id INTEGER PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE,
micropost_id INTEGER REFERENCES microposts(id)
);
INSERT INTO activities (id, created_at, micropost_id)
VALUES (1, current_timestamp, 1),
(2, current_timestamp - interval '3 hours', 1),
(3, current_timestamp - interval '2 hours', 2)
您在問題中聲明要根據activities.created_at的順序“distinct micropost_id”。 這很容易通過降created_at(訂購這些活動的1, 3, 2
),但兩者1
和2
有1相同micropost_id所以,如果你想查詢返回只是微柱的ID,它應該返回1, 2
或2, 1
?
如果您可以回答上述問題,則需要采用您的邏輯並將其移至查詢中。 讓我們說,我認為這很可能,你希望這是一個最近作用的微博列表。 在這種情況下,您希望按最近活動的降序對微博進行排序。 Postgres可以通過多種方式為您做到這一點,但最簡單的方法是:
SELECT micropost_id
FROM activities
JOIN microposts ON activities.micropost_id = microposts.id
GROUP BY micropost_id
ORDER BY MAX(activities.created_at) DESC
請注意,我已經刪除了SELECT DISTINCT
位,轉而使用GROUP BY
,因為Postgres會更好地處理它們。 MAX(activities.created_at)
位告訴Postgres,對於具有相同micropost_id的每組活動,僅按最近的排序。
您可以將上述內容翻譯為Rails,如下所示:
Micropost.select('microposts.*')
.joins("JOIN activities ON activities.micropost_id = microposts.id")
.where('activities.user_id' => id)
.group('microposts.id')
.order('MAX(activities.created_at) DESC')
希望這可以幫助! 如果您想了解有關查詢如何工作的更多信息,可以使用此sqlFiddle 。
請嘗試以下代碼
Micropost.select('microposts.*, activities.created_at')
.joins("INNER JOIN activities ON (activities.micropost_id = microposts.id)")
.where('activities.user_id= ?',id)
.order('activities.created_at DESC')
.uniq
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.