开发者

All the post on their last version

开发者 https://www.devze.com 2023-04-12 10:37 出处:网络
On my database, I have to show a preview with all the posts with their last content and I don\'t really know how to do it.

On my database, I have to show a preview with all the posts with their last content and I don't really know how to do it.

CREATE TABLE IF NOT EXISTS `posts` (
`id` int(11) NOT NULL auto_increment,
`post_id` int(11) NOT NULL,
`title` varchar(255) NOT NULL,
`body` text NOT NULL,
`created` date NOT NULL,
PRIMARY KEY  (`id`),
KEY `post_id` (`post_id`)) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

INSERT INTO `posts开发者_开发百科` (`id`, `post_id`, `title`, `body`, `created`) VALUES 
(1, 1, 'hello world', 'this is the first post', '2011-10-10'), 
(2, 2, 'the second post', 'and this is the second post', '2011-10-10'), 
(3, 2, 'second post', 'title is modified, this is a better version', '2011-10-11');

So the result has to be the post with id 1 and 3. The second post, appears twice because there are two versions on different dates. The dates of the posts marks which version is newer.

I need to display the last state of all the post. How can I do that?


This is a Top-N Per Group Problem:

Here is how you would do it:

SELECT A.* FROM (
    SELECT 
        p.*,
        IF( @p <> ID, @n := 1, @n := @n+1 ) AS r, 
        @p := post_id
    FROM
        posts p
    ORDER BY post_id, created DESC
    ) AS A
WHERE r = 1

For more information: http://www.artfulsoftware.com/infotree/queries.php#104

Explanation:

SELECT A.* FROM (
    SELECT 
        p.*,
        IF( 
                @p <> ID,   /* check if this record is a new post_id */
                @n := 1,    /* if it is a new post_id, reset the counter to 1 */
                @n := @n+1  /* other wise, increment the counter */
            ) AS r,
        @p := post_id   /* assign the post_id of this record to @p to use in the IF statement */
    FROM
        posts p
    ORDER BY 
        post_id,     /*first, order by postID so we scan over all versions of posts together */
        created DESC /* then order by createDate DESC so the newest versions of each post are first */
    ) AS A
WHERE r = 1

Sample Results (of the subquery):

id | post_id | title | body | created    | r | @p
1  | 1       | ...   | ...  | 10/10/2011 | 1 | 1
3  | 2       | ...   | ...  | 10/11/2011 | 1 | 2
2  | 2       | ...   | ...  | 10/10/2011 | 2 | 2


How about this? ID is being used to tell which one is newer.

SELECT id, post_id, title, body, created
FROM posts 
WHERE (post_id, id) IN (SELECT post_id, MAX(id) FROM posts GROUP BY post_id)

If you need to use date (what if there are two posts on the same date?)

SELECT id, post_id, title, body, created
FROM posts 
WHERE (post_id, created) IN (SELECT post_id, MAX(created) FROM posts GROUP BY post_id)
0

精彩评论

暂无评论...
验证码 换一张
取 消