假设我使用以下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
声明 - 这可能吗?
注意:
答案 0 :(得分:1)
您需要两个查询才能获得您制作的表单:
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
用作列名,这也与基本数据类型冲突。
比较这个相关案例:
答案 1 :(得分:1)
但是,我不禁认为有一种方法可以只涉及一个SELECT语句 - 这可能吗?
技术上:是的。如果您真的想要json
中的数据,可以使用PostgreSQL(9.2+)使用json
functions生成数据,如:
SELECT row_to_json(sq)
FROM (
SELECT array_to_json(ARRAY(
SELECT row_to_json(p)
FROM (
SELECT *, ARRAY(SELECT id FROM comment WHERE post_id = post.id) AS comment
FROM post
) AS p
)) AS post,
array_to_json(ARRAY(
SELECT row_to_json(comment)
FROM comment
)) AS comment
) sq;
但我不确定它是否值得 - 在没有限制/分页的情况下转储所有数据通常不是一个好主意。