我正在开发一个需要独特查询的博客应用。
问题:我需要显示一个父帖子,所有孩子的帖子(在要求分页之前达到某个数字),以及每个子帖子和父母最多5条评论。
我写了这个查询,但它不起作用,因为它只会返回属于父帖的5条评论。
SELECT
posts.id, posts.postTypeId, posts.parentId, posts.ownerUserId, posts.body
, users.id AS authorId, users.displayname AS authorDisplayName
, comments.id AS commentId, comments.text AS commentText
, comments.commentOwnerUserId, comments.commentOwnerDisplayName
FROM posts
JOIN users ON posts.owneruserid = users.id
LEFT JOIN ( SELECT comments.id, comments.postId, comments.text, commenters.id AS commentOwnerUserId, commenters.displayname AS commentOwnerDisplayName
FROM comments
JOIN users AS commenters ON comments.userid = commenters.id
ORDER BY comments.createdat ASC
LIMIT 0,5 ) AS comments ON comments.postid = posts.id
WHERE posts.id = @postId OR posts.parentId = @postId
ORDER BY posts.posttypeid, posts.createdAt
查询返回父帖子,它的所有孩子以及它遇到的前5条评论(通常它们属于父级,因为我们按postTypeId排序,而父级是第一篇帖子)。如果第一篇文章没有5条评论,它将在下一篇文章中移动并返回这些评论,直到达到5条限制。
我需要的是返回一个父帖子及其所有子帖子,以及每个孩子(父母)最多5条评论。我还需要每个帖子和评论的所有者数据。
更新如果可以扩展,我可以使用多个查询执行此操作。唯一的条件是父和子帖子检索发生在同一个查询中。
知道怎么写这样的查询吗?我在下面包含了我的架构。
/* Posts table */
CREATE TABLE `posts` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`posttypeid` int(10) NOT NULL,
`parentid` int(10) DEFAULT NULL,
`body` text NOT NULL,
`userid` int(10) NOT NULL,
`createdat` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `parentId` (`parentid`)
KEY `userId` (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=572 DEFAULT CHARSET=utf8
/* Comments table */
CREATE TABLE `comments` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`postid` int(10) NOT NULL,
`userid` int(10) NOT NULL,
`text` text NOT NULL,
`createdat` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `postId` (`postid`),
KEY `userId` (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
/* users table */
CREATE TABLE `users` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`email` varchar(50) NOT NULL,
`displayname` varchar(50) NOT NULL,
`createdat` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8
答案 0 :(得分:2)
听起来你正在寻找存储分层数据。这不是一个难题,因为它有点耗时。我建议你阅读几年前由Mike Hillyer撰写的一篇名为Managing Hierarchical Data in MySQL的非常好的文章。它有一些非常好的概念建议以及你正在设计的那种系统的示例实现。绝对阅读“查找节点的直接下属”部分。 :)
答案 1 :(得分:2)
我假设你会有某种分页来限制顶级帖子的数量。
您还需要一些关于评论数量,帖子表格中的子信息或帖子摘要表的摘要信息。
评论表需要逐列列出
1:获取所有父帖子,(parentId = 0)&构造postids的IN子句
2:通过传递1中获得的postid来获取所有儿童帖子,按postid排序,这将有助于隔离。将这些帖子添加到整个IN子句中 通过传递来自1&的postids获得评论2。 使用评论数量限制评论数量&序列列 例如:加入评论& post_summary post_comment_seq之间(noofcommentsforthepost - 5)和noofcommentsforthepost
您可以在此处查看条款效果Performance of MYSQL "IN"
答案 2 :(得分:2)
我已经从Your Previous Question调整了另一个查询,只是在您的ParentID上包含一个WHERE子句。那是我不知道你想要限制回报的条件。我添加了帖子ID =你想要的那个或者ParentID =你想要的那个。
通过POST ID获得ORDER,它自然会将起始父ID放在第一个位置,因为其他ID将按顺序从其中派生出来。我想这会再次解决你。
答案 3 :(得分:1)
我认为每个孩子只有一个父母。然后,我认为这将有效:
SELECT p.* <-- post details
, u.* <-- user details
, cc.* <-- comment details
FROM
( ( SELECT parentid AS id
FROM posts
WHERE posts.id = @mypostid <-- the id of the post we want
)
UNION ALL
( SELECT child.id
FROM posts AS parent
JOIN posts AS child
ON child.parentid = parent.id
WHERE parent.id =
( SELECT posts.parentid
FROM posts
WHERE posts.id = @mypostid) <-- the id of the post we want
ORDER BY child.createdat <-- any order you prefer
LIMIT x, 5 <-- 5 children posts
)
) AS pp
JOIN posts p
ON p.id = pp.id
JOIN users
ON users.id = p.userid
JOIN comments cc
ON cc.postid = pp.id
WHERE cc.postid IN
( SELECT c.id
FROM comments c
WHERE c.postid = pp.id
ORDER BY c.createdat <-- any order you prefer
LIMIT y, 5 <-- 5 comments for every post
)
对于前五个孩子的帖子,x,5
应该替换为0,5
,对于前五个评论,y,5
应该替换为0,5
5,5
。然后,10,5
代表接下来的五个,This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
代表接下来的五个,等等。
<强>更新强>
抱歉,我的错误。上面给出了错误:
{{1}}
我会高兴地解决这个问题:)