2017-04-03 33 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

相关问题