【问题标题】:Postgres - connect three tables and use aggregate functions on data in a queryPostgres - 连接三个表并在查询中对数据使用聚合函数
【发布时间】:2021-08-18 03:51:36
【问题描述】:

我有三张桌子:

帖子:

  id  |  title
------------------
  1   |  post1
  2   |  post2
  3   |  post3
  4   |  post4

评论:

  post_id  |  content
-----------------------
     1     |  asd
     1     |  dsad
     1     |  awtihaw
     2     |  aaaaa
     2     |  bbbbbbbb
     4     |  asdasd

投票:

  post_id  |  value
-----------------------
     1     |  1
     2     |  1
     2     |  -1
     3     |  1
     3     |  1
     3     |  1
     3     |  -1

问题

我需要计算每个帖子有多少个cmet和多少个赞。

这是我的查询:

SELECT posts.id, COUNT(comments.post_id) as comments, SUM(votes.value) as votes
FROM posts
LEFT JOIN comments ON posts.id = comments.post_id
LEFT JOIN votes ON posts.id = votes.post_id
GROUP BY posts.id
ORDER BY posts.id

事实上我得到了一个结果,但是在结果中它说

post ID 为 13 票3 cmets

实际上它只有一票和三个 cmets。 如何正确连接三个表以显示正确的结果?我需要能够仅在查询中执行此操作,最好只在一个查询中执行此操作。

【问题讨论】:

    标签: sql postgresql aggregate-functions


    【解决方案1】:

    一个简单的解决方案使用相关子查询:

    SELECT p.id,
           (SELECT COUNT(*)
            FROM comments c
            WHERE p.id = c.post_id
           ) as num_comments,
           (SELECT SUM(v.value)
            FROM votes v
            WHERE p.id = v.post_id
           ) as net_votes
    FROM posts p
    ORDER BY p.id;
    

    使用comments(post_id)votes(post_id, value)posts(id) 上的索引,这可能是最快的解决方案。

    【讨论】:

      【解决方案2】:

      我认为 JOIN 不是我们应该尝试的方式。

      在这里,当我们使用 JOIN 时,对于同一请求的每个投票,都会在结果中重复帖子的 cmets。 同样,每个 cmets 都会重复投票。

      在给定的示例中,您仅获得了 cmets 的正确值,因为我们在 POST_ID 1 的投票中只有一行。

      我们必须使用 INNER 查询来获得正确的结果,而不是 JOIN。

      【讨论】:

        【解决方案3】:

        你应该分别在commentsvotes聚合,然后加入posts

        SELECT p.id, c.comments_count, v.votes_sum
        FROM posts p
        LEFT JOIN (
          SELECT post_id, COUNT(post_id) comments_count
          FROM comments 
          GROUP BY post_id
        ) c ON p.id = c.post_id
        LEFT JOIN (
          SELECT post_id, SUM(value) votes_sum
          FROM votes 
          GROUP BY post_id
        ) v ON p.id = v.post_id
        ORDER BY p.id
        

        对于没有任何 cmets 或投票的帖子,这将返回 NULL
        如果你想改用0,请使用COALESCE()

        SELECT p.id, 
               COALESCE(c.comments_count, 0) comments_count, 
               COALESCE(v.votes_sum, 0) votes_sum
        FROM .....
        

        【讨论】:

          猜你喜欢
          • 2016-02-05
          • 1970-01-01
          • 2015-09-23
          • 1970-01-01
          • 1970-01-01
          • 2015-06-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多