Postgresql查询在过去24小时内查找最高投票表格

时间:2017-04-03 02:23:23

标签: sql postgresql

我有一个复杂的PostgreSQL数据库查询,我在构建时遇到了困难。我有两个表:post表和votes表。以下是它们的样子:

post表格 - 我只包含了id,因为其他列对我的问题并不重要

 ---- 
| id |
 ---- 

votes表格vote_type可以是1(upvote),-1(downvote)或0(中立)。 post_id是单票的帖子ID的ID。

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

以下是我要实现的目标:查询过去24小时内投票最多的前10个帖子

我首先构建了以下查询:

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;

返回类似的内容:

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

它与正确的帖子略有作用但投票栏只显示过去24小时内的投票总数,而不是自帖子发布以来的总票数(这就是我想要的)。原因是因为我只对过去24小时内的投票进行总结,而不是自该职位创建以来的所有投票。

post id 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的初学者。我还要求我如何简化上面的查询。谢谢你的帮助。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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(也称为{{} {1}})上面我将结果限制在过去24小时内投票的前10个帖子中。如果在过去24小时内有少于10个投票的帖子,那么它只返回该号码。如果您仍然需要10条记录,并且对剩余记录是半随机选择感到满意,那么请将INNER JOIN更改为JOIN,并将RIGHT JOIN添加到外部LIMIT 10的末尾声明。如果您需要额外的记录但具有特定的排序模式,那么在我可以为其编码之前,您需要指定模式。

其次,SELECT将在当前日期时间之前24小时生成日期时间。它所属的NOW() + INTERVAL '-1 day'声明将我们的结果限制为过去24小时内的投票。

如果没有WHERE,则内部查询将返回GROUP BYpost_id的行数,因为有votesTotal符合post_id条件的行。 WHERE(与GROUP BY一起使用)可以为每个SUM减少一行。

post_id为我们提供了由内部查询的其余部分生成的第一个 10条记录。为了确保它们也是 top 10,我确保使用LIMIT 10对列表进行了排序。

进一步阅读...

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

如果您有任何问题或意见,请相应发表评论。

答案 2 :(得分: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

的列