2016-02-12 35 views
1

我想爲特定用戶選擇所有線程主題,但我想通過最近發送的消息以最近的線程進行排序。這是我的數據庫模式。窗口函數,試圖通過created_at從連接表中的列進行排序而不進行分組

create table thread (
    id bigserial primary key, 
    subject text not null, 
    created timestamp with time zone not null default current_timestamp 
); 

create table thread_account (
    account bigint not null references account(id) on delete cascade, 
    thread bigint not null references thread(id) on delete cascade 
); 
create index thread_account_account on thread_account(account); 
create index thread_account_thread on thread_account(thread); 

create table message (
    id bigserial primary key, 
    thread bigint not null references thread(id) on delete cascade, 
    content text not null, 
    account bigint not null references account(id) on delete cascade, 
    created timestamp with time zone not null default current_timestamp 
); 
create index message_account on message(account); 
create index message_thread on message(thread); 

然後我在做一個查詢像

select * 
FROM thread_account 
JOIN thread on thread.id = thread_account.thread 
JOIN message on message.thread = thread_account.thread 
WHERE thread_account.account = 299 
ORDER BY message.created desc; 

但這只是還給所有線程科目那裏是一個信息的每個條目的列表。 (JOIN消息message.thread = thread_account.thread)似乎是問題。我被告知我需要一個窗口函數,但似乎無法找出它們。這是Postgres的方式。

+0

我不理解你的問題,請進一步解釋,或寫你想 – Monty

+0

比較遺憾的是什麼輸出。所以我有5個線程,線程只有id,創建和主題列。但我想按照最近發送的消息的順序返回線程。 IE message.created而不是thread.created。消息通過thread_account連接到線程。 我只會介紹按照最近消息的順序返回的5個線程。但我目前正在返回1000個條目(每個消息在整個數據庫中都有一個)。 這有道理嗎? – elcapitan

+0

正在處理您的查詢。 – Monty

回答

0

我認爲你正在尋找的東西,如:

select * 
FROM thread_account 
JOIN thread on thread.id = thread_account.thread 
JOIN message on message.thread = thread_account.thread 
WHERE thread_account.account = 299 
ORDER BY MAX(message.Created) OVER (PARTITION BY thread.id) desc; 

的小調整是在ORDER BY窗函數。這會將結果集分區爲thread.id,因此每個thread.id最終都會有大塊記錄,然後爲每個記錄塊找到max(message.created)。然後它使用該max(message.created)對結果集進行排序。開始時,窗口函數有點棘手,但是隻要將它們視爲分塊記錄(分區),然後將某種聚合或函數應用於該塊中的某個字段,例如Max()


正如您的評論中提到,你不希望看到的消息中的信息,而不僅僅是線程。您只需在查詢的SELECT部分指定您想要的結果集中的哪些字段。您可以使用GROUP BYDISTINCT爲每個線程獲取單個記錄。

此外,我們還可以通過複製該窗口函數向上進入Select部分以及顯示在結果的最後一條消息日期:

SELECT DISTINCT 
    thread_account.*, 
    thread.*, 
    MAX(message.Created) OVER (PARTITION BY thread.id) as Last_Message_Date 
FROM thread_account 
JOIN thread on thread.id = thread_account.thread 
JOIN message on message.thread = thread_account.thread 
WHERE thread_account.account = 299 
ORDER BY MAX(message.Created) OVER (PARTITION BY thread.id) desc; 

如果你只是想從任ThreadThread_Account某些字段,那麼你只得到查詢像SELECT DISTINCT Thread.Id, Thread_Account.Account, etc..

+0

附加到線程所以這仍然返回我在數據庫中的所有消息的所有條目。線程1的IE 50消息,線程2的300我正在尋找線程的(不是消息和消息條目,只是通過創建的消息來排序)。我們正在接近!感謝您的幫助 – elcapitan

+0

Gotcha。我已經爲使用DISTINCT或GROUP BY的答案添加了一些額外的幫助,以及如何更明確地說明從連接的表中返回哪些字段。 – JNevill

+0

哦,這是awesoe!非常感謝。這解決了它。非常感謝你的幫助。 – elcapitan

0

非常方便distinct onSELECT部分更明確更容易:

select distinct on (t.id) * 
from 
    thread_account ta 
    inner join 
    thread t on t.id = ta.thread 
    inner join 
    message m on m.thread = ta.thread 
where ta.account = 299 
order by t.id, m.created desc 

對於剛剛的線程信息做,而不是:

select distinct on (t.id) t.* 
相關問題