示例:我有一些articles
和comments
,我希望得到这样的内容:
[{
title: "Article 1",
content: "Super long article goes here",
comments: [
{ author: "Troll", message: "You suck, Sir!" },
{ author: "SpamBot", message: "http://superawesomething.com/"}
]
},{
title: "Article 2",
content: "Another long article goes here",
comments: [ ... ]
}]
现在我看到两个解决方案:
IN
条件的评论,最后将评论添加到相应的文章中。articles.content
这样的有效负载 - 除非有办法进行加入我不知道。我希望我的SQL文盲能让我错过这个简单的解决方案。
答案 0 :(得分:6)
您可以使用聚合和/或子查询来执行此操作。类似的东西:
select title, content, json_agg(comments.author, comments.message) as comments
from articles
join comments on articles.article_id = comments.article_id
group by article_id;
如果你需要将它聚合成一个字符串/ json / something - 只需将它包装到另一个聚合查询中,如下所示:
select json_agg(sub)
from (
select title, content, json_agg(comments.author, comments.message) as comments
from articles
join comments on articles.article_id = comments.article_id
group by article_id) sub;
这是一个Postgres查询。没有Mysql的经验。
答案 1 :(得分:1)
这是一个MySQL解决方案:
SELECT CONCAT( '[ { '
,GROUP_CONCAT( CONCAT( 'title: "', REPLACE( a.title, '"', '\"' ), '"'
,', contents: "', REPLACE( a.content, '"', '\"' ), '"'
,', comments: ', a.comments
)
SEPARATOR ' }, { '
)
,' } ]'
)
FROM (SELECT a1.title
,a1.content
,CONCAT( '[ { '
,GROUP_CONCAT( CONCAT( 'author: "', REPLACE( c.author, '"', '\"' ), '"'
,', message: "', REPLACE( c.message, '"', '\"' ), '"'
)
SEPARATOR ' }, { '
)
,' } ]'
) as comments
FROM articles a1
LEFT OUTER
JOIN comments c
ON c.articleId = a1.articleId
GROUP BY a1.title, a1.content
) a
;
当字符串变大时,需要进行一些调整。最好每篇文章返回一行:
SELECT a1.title
,a1.content
,CONCAT( '[ { '
,GROUP_CONCAT( CONCAT( 'author: "', REPLACE( c.author, '"', '\"' ), '"'
,', message: "', REPLACE( c.message, '"', '\"' ), '"'
)
SEPARATOR ' }, { '
)
,' } ]'
) as comments
FROM articles a1
LEFT OUTER
JOIN comments c
ON c.articleId = a1.articleId
GROUP BY a1.title, a1.content
SQLFiddle:http://sqlfiddle.com/#!2/5edcd/13
答案 2 :(得分:0)
如果两个查询都在同一个事务中完成,则第一种方法是正确的。它主要在服务器端交换CPU时间(对于代价高昂的第二个查询),在客户端的某些CPU时间和两者之间的网络流量。
虽然第一种方法最初在网络流量方面看起来很昂贵,但是一些在线协议支持以有效的方式引用相同值的列。在这种情况下,不会为每一行传输由于连接而重复的列值。您应该检查实际产生的流量,开销可能没有看起来那么大
在客户端,您可以使用articles
的主键将所有article
存储在类似hashmap的对象中。在接收行时,您会向列表添加注释,每个注释都会被该键索引。通过根据article
的主键对服务器端的行进行排序,可以提高效率,使您能够在客户端上使用自然排序的列表列表。与第一种方法相比,构建这种结构是cpu-time-tradeoff
我的判决:使用JOIN
。
答案 3 :(得分:0)
PostgreSQL的json_agg功能的等效功能已列入MySQL的下一个版本的议程。
这将非常有帮助。
您可以查看(有提示与当前版本实现相同类型的结果):