【问题标题】:select articles + multiple comments for each article in one query在一个查询中为每篇文章选择文章 + 多条评论
【发布时间】:2020-12-20 11:50:17
【问题描述】:

我的 postgresql 数据库中有 2 个表。简化后,它们看起来像这样:

// table: articles
+----+-----------+---------------+
| id | title     | body          |
+----+-----------+---------------+
| 1  | hello     | world         |
| ...                            |
+----+-----------+---------------+

// table: comments
+----+-----------+---------------+
| id | articleid | comment       |
+----+-----------+---------------+
| 1  | 1         | looks cool!   |
| ...                            |
+----+-----------+---------------+

我想制作一个包含所有文章的概览页面 + 每篇文章的最后 3 个 cmets。这可以通过一个查询来实现吗?

我的查询现在看起来像这样(nodeJS):

let query, values, result;

let ret = [];

// query to select all articles, ordered by ID desc
query = 'SELECT id, title FROM articles ORDER BY id DESC';
result = await postgresql.query(query, []);

// store all rows in a constant
const articles = result.rows;

// loop over each article
articles.forEach(article => {
  // fetch the last 3 comments for each article
  query = 'SELECT id, comment FROM comments WHERE articleid = $1 ORDER BY id DESC LIMIT 3';
  values = [article.id];
  result = await postgresql.query(query, values);

  // store the comments in a constant
  const comments = result.rows;

  // push the article information (ID + title) and the comments in the ret array
  ret.push({
    articleID: article.id,
    title: article.title,
    comments: comments
  });
});

// ret now contains an array of objects of articles + comments
return ret;

我想知道是否可以将两个查询合并为 1,或(如果不可能),这是执行此操作的最佳性能方式。

请注意,这两个表都比我在此处描述的简化版本要大。目前我有 + 1,700 篇文章和 +100,000 个 cmets。

【问题讨论】:

    标签: javascript sql node.js postgresql greatest-n-per-group


    【解决方案1】:

    一个选项使用横向连接:

    select a.id, a.title, c.id, c.comment
    from articles a
    cross join lateral (
        select c.*
        from comments c
        where c.articleid = a.id
        order by id desc
        limit 3
    ) c
    order by a.id desc, c.id desc
    

    【讨论】:

      【解决方案2】:

      我相信,一个简单的:

      select id, comment from 
      (select a.id, c.comment, dense_rank() over PARTITION BY a.id ORDER BY c.id DESC) as rn from articles a join comments c on a.id = c.article_id) t
      where t.rn <= 3;
      

      所以是的,你只需要使用“DENSE_RANK()”函数https://www.postgresqltutorial.com/postgresql-dense_rank-function/

      【讨论】:

      • 谢谢。我去看看。
      • 这里rank()、dense_rank() 和row_number() 将在输出方面做同样的事情,但row_number() 在性能方面会比其他人更好
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      相关资源
      最近更新 更多