sql - 使用一个 SELECT 而不是两个来服务于旁加载的 API 请求?

标签 sql performance postgresql select join

假设我使用以下 SQL 创建了两个表, 这样 post 有很多 comment:

CREATE TABLE IF NOT EXISTS post (
            id          SERIAL PRIMARY KEY,
            title       VARCHAR NOT NULL,
            text        VARCHAR NOT NULL
        )

CREATE TABLE IF NOT EXISTS comment (
            id          SERIAL PRIMARY KEY,
            text        VARCHAR NOT NULL,
            post_id  SERIAL REFERENCES post (id)
        )

我希望能够查询这些表以便提供响应 看起来像这样:

{
  "post" : [
    { id: 100,
      title: "foo",
      text: "foo foo",
      comment: [1000,1001,1002] },
    { id: 101,
      title: "bar",
      text: "bar bar",
      comment: [1003] }
  ],
  "comment": [
    { id: 1000,
      text: "bla blah foo",
      post: 100 },
    { id: 1001,
      text: "bla foo foo",
      post: 100 },
    { id: 1002,
      text: "foo foo foo",
      post: 100 },
    { id: 1003,
      text: "bla blah bar",
      post: 101 },
  ]
}

天真地这样做会涉及到 SELECT 语句, 第一个是

SELECT DISTINCT ON(post.id), post.title, post.text, comment.id
FROM post, comment
WHERE post.id = comment.post_id

...第二个是

SELECT DISTINCT ON(comment.id), comment.text, post.id
FROM post, comment
WHERE post.id = comment.post_id

但是,我不禁想到有一种方法可以做到这一点 只有一个 SELECT 语句 - 这可能吗?


注意事项:

  • 我正在使用 Postgres,但我不需要特定于 Postgres 的解决方案。任何标准 SQL 解决方案都应该可以。
  • 上面的查询只是说明性的,它们并不能准确地告诉我们目前需要什么。
  • 这里看起来天真的解决方案是在相同的两个表上执行相同的连接,只是每次在不同的表上执行不同的操作。这无疑留下了改进的余地。
  • 看来 Rails 中的 ActiveModel 序列化程序 already do this - 如果有熟悉他们的人愿意对他们的幕后工作方式发表意见,那就太好了。

最佳答案

您需要两个查询来获取您布置的表单:

SELECT p.id, p.title, p.text, array_agg(c.id) AS comments
FROM   post p
JOIN   comment c ON c.post_id = p.id
WHERE  p.id = ???
GROUP  BY p.id;

或者更快,如果您真的想检索所有或大部分帖子:

SELECT p.id, p.title, p.text, c.comments
FROM   post p
JOIN  (
   SELECT post_id, array_agg(c.id) AS comments
   FROM   comment
   GROUP  BY 1
   ) c ON c.post_id = p.id
GROUP  BY 1;

加上:

SELECT id, text, post_id
FROM   comment
WHERE  post_id = ??;

单一查询

SQL 每次查询只能发送一个 结果类型。对于单个查询,您必须合并两个表,列出冗余的列以进行发布。这与您问题中的预期答复相冲突。您必须放弃两个相互冲突的要求之一。

SELECT p.id, p.title, p.text AS p_text, c.id, c.text AS c_text
FROM   post p
JOIN   comment c ON c.post_id = p.id
WHERE  p.id = ???

另外:列 comment.post_id 应该是 integer,而不是 serial!此外,列名可能只是为了快速展示。您不会使用非描述性的 text 作为列名,这也与基本数据类型冲突。 比较这个相关案例:

关于sql - 使用一个 SELECT 而不是两个来服务于旁加载的 API 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25205026/

相关文章:

mysql - 如何在 MySQL 中返回数据透视表输出?

java - 如何动态更改 sql 'like' 运算符?

c# - 随机化对象的位置放置

sql - MySQL性能查询

postgresql - 类型 uuid : "" or "null" in PosgreSQL copy command 的输入语法无效

postgresql - 简单的更新查询花费的时间太长 - Postgres

sql - 您在 SQL Server 中做什么来创建或更改?

jquery - Localstorage 与 Cookie - 性能

postgresql - Postgres : MD5 Password/Plain password

c# - 为单个标签 .Net 组合两个资源键