I’m working on a blogging app that requires a unique query.
Problem: I need to display one parent post, all it’s children posts (up to a certain number before requiring pagination), and up to 5 comments associated with each child post, and the parent.
I wrote this query, but it doesn’t work because it will return only 5 comments that belong to the parent post.
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
The query returns the parent post, all it’s children, and the first 5 comments it encounters, (usually they belong to the parent because we are ordering by postTypeId, and the parent is the first post). If the first post doesn’t have 5 comments, it moves on the next post and returns those comments, until the 5 limit is reached.
What I need is to return one parent post and all it’s children posts, and up to 5 comments for each child, the parent. I also need the owner data for each post and comment.
UPDATE I’m open to doing this with more than one query if it will scale well. The only condition is that the parent and children posts retrieval happens in the same query.
Any idea how I can write such a query? I included my schema below.
/* 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
I take as granted that every child has exactly one parent. Then, I think this will work:
The
x,5should be replaced with0,5for first five childen posts andy,5with0,5for first five comments. Then with5,5for next five,10,5for next five, etc.UPDATE
Sorry, my mistake. The above gives the error:
I’ll wrap my head up to work around this 🙂