2017-04-03 31 views
0

我有一個複雜的PostgreSQL數據庫查詢,我在構建時遇到困難。我有兩個表:一個post表和一個votes表。下面是他們的樣子:Postgresql查詢在過去24小時內查找排名最高的表格

post表 - 我只包括了id因爲其他列不是我的問題很重要

---- 
| id | 
---- 

votes表 - vote_type可以是1(給予好評),-1(downvote)或0(中性)。 post_id是單次投票帖子ID的ID。

---- --------- ----------- -------------------------------- 
| id | post_id | vote_type | timestamp      | 
---- --------- ----------- -------------------------------- 
| 1 | 4  | 1   | 2017-03-30 12:17:12.246765-07 | 

這裏就是我想實現:

SELECT postsTable.*, votesTable.votes 
FROM posts AS postsTable 
RIGHT JOIN (
    SELECT sum(vote_type) votes, post_id 
    FROM votes 
    WHERE (extract(day from age(now(), timestamp)) < 1) 
    GROUP BY post_id) 
    AS votesTable 
    ON (postsTable.id = votesTable.post_id) 
ORDER BY votes DESC NULLS LAST LIMIT 10; 

:過去24小時

我首先構建以下查詢中查詢前10名得票最多的帖子返回類似於:

---- ---------------------- ------- 
| id | other_colums_between | votes | 
---- ---------------------- ------- 
| 8 | ...     | 1  | 

它與正確的帖子略有差異,但是投票欄只顯示了過去24小時內的投票總數,而不是自帖子發佈以來的總投票數(這正是我想要的)。原因是因爲我總結了過去24小時內的投票數,而不是自帖子創建以來的所有投票數。

postid 8有10票。查詢只返回1票,因爲在過去的24小時內只有一個upvote。

因此,查詢應該返回:

---- ---------------------- ------- 
| id | other_colums_between | votes | 
---- ---------------------- ------- 
| 8 | ...     | 10 | 

所以我知道我必須解決,但我不知道該怎麼做。我已經嘗試了下面的查詢,但這不是我想要的,但我覺得我正在接近。儘管如此,我還沒有在過去24小時內對帖子進行過濾。

SELECT postsTable.*, votesTable.vote_type, extract(day from age(now(), votesTable.timestamp)) age 
FROM posts AS postsTable 
RIGHT JOIN (SELECT * FROM votes) 
AS votesTable ON (postsTable.id = votesTable.post_id) 
ORDER BY vote_type DESC NULLS LAST LIMIT 10; 

返回:

---- ---------------------- ----------- ----- 
| id | other_colums_between | vote_type | age | 
---- ---------------------- ----------- ----- 
| 8 | ...     | 1   | 3 | 

正如你能告訴我在SQL初學者。我還要求提供一些關於如何簡化上述查詢的建議。感謝您的幫助。

+0

所以,如果我的理解是正確的,你應該擺脫年齡(這其中'WHERE(提取物(現在每天(),時間戳) )<1)' –

+0

要澄清,neutral(0)沒有資格作爲投票嗎? – toonice

+0

是0沒有資格作爲投票@toonice –

回答

0

我可以想到這個,但我沒有測試。

SELECT postsTable.*, votesTable.votes FROM posts AS postsTable RIGHT JOIN (SELECT sum(vote_type) votes, post_id FROM votes WHERE votes.post_id IN (select unique v.post_id from votes as v where(extract(day from age(now(), timestamp)) < 1)) GROUP BY post_id) AS votesTable ON (postsTable.id = votesTable.post_id) ORDER BY votes DESC NULLS LAST LIMIT 10; 
+0

對不起,我得到一個語法錯誤'在或接近「v」'。 –

0

請嘗試...

SELECT posts.*, 
     votesTotal AS Votes 
FROM posts 
JOIN 
(
    SELECT post_id AS post_id, 
      SUM(vote_type) AS votesTotal 
    FROM votes 
    WHERE timestamp > NOW() + INTERVAL '-1 day' 
    GROUP BY post_id 
    ORDER BY votesTotal DESC 
    LIMIT 10 
) postCounter ON postCounter.post_id = posts.id; 

首先,RIGHT JOIN將從Posts從子查詢其相應的記錄相匹配的記錄所有而使用JOIN(又名一個INNER JOIN)以上我將結果限制在過去24小時的投票中排名前10位的職位。如果在過去24小時內有少於10個投票的帖子,那麼它只會返回那個數字。如果您仍然需要10條記錄,並且對其餘記錄是半隨機選擇感到滿意,則將JOIN更改爲RIGHT JOIN,並將LIMIT 10添加到外部SELECT語句的末尾。如果您需要額外的記錄,但需要使用特定的排序模式,那麼您需要先指定模式,然後才能對其進行編碼。

其次,NOW() + INTERVAL '-1 day'將在當前日期時間之前24小時產生日期時間。其中的一部分WHERE聲明將我們的結果限制在過去24小時內的那些投票中。

沒有GROUP BY內查詢會因爲有與post_id行滿足我們WHERE標準與post_idvotesTotal返回儘可能多的行。 GROUP BY(與SUM一起)具有將每個post_id減少到一行的效果。

LIMIT 10給我們第一個由內部查詢的其餘部分產生的10條記錄。爲了確保它們也是top 10我確保使用ORDER BY對列表進行排序。

進一步閱讀...

http://www.sqlines.com/postgresql/how-to/dateadd

https://www.w3schools.com/sql/sql_groupby.asp

https://www.w3schools.com/sql/sql_join.asp(維恩圖可以是特別有幫助)

https://www.w3schools.com/sql/sql_orderby.asp

https://www.postgresql.org/docs/8.1/static/queries-limit.html

如果您有任何問題或意見,請相應發表評論。

+0

抱歉,這不起作用。它仍然返回相同的結果。另外,PG爲WHERE情況拋出了一個語法錯誤。我不得不將其更改爲WHERE timestamp now()+ INTERVAL'-1 day''(我從未使用過INTERVAL,我認爲這應該如何完成,因爲這會返回結果)。感謝您花時間評論併發布答案。 –

+0

我的歉意 - 我分心了,忘了將我的代碼從默認的MySQL更改爲PostgreSQL。你的改變是與MySQL的DATE_ADD()相同的PostgreSQL。我糾正了我的答案。 代碼現在可以工作嗎? – toonice

+0

不用擔心。不,不是的。返回的結果仍然相同。 –

0

你會希望把在WHERE子句您外部表,而不是你的內心表,因爲你要過濾的帖子按日期,而不是

SELECT postsTable.*, votesTable.votes 
FROM posts AS postsTable 
RIGHT JOIN (
    SELECT sum(vote_type) votes, post_id 
    FROM votes 
    GROUP BY post_id) 
    AS votesTable 
    ON (postsTable.id = votesTable.post_id) 
WHERE (extract(day from age(now(), timestamp)) < 1) 
ORDER BY votes DESC NULLS LAST LIMIT 10; 

(假設你的posts表也有一欄叫timestamp

相關問題