MySQL Query - 每组最近的条目

时间:2011-02-09 11:52:27

标签: mysql group-by sql-order-by

我正在尝试在表格中为每个组选择最近的条目。

假设我有一个表“blog_posts”,其中包含“id”列(所有唯一,自动递增),“post_cat”,可以是值“category1”或“category2”或“category3”,以及“publish_status” “列可以是'在线'或'离线'的值。

如何为每个类别选择最新的条目?

我现在有以下内容,但几乎感觉它是随机选择的:

select * FROM `blog_posts` WHERE (publish_status = 'online') GROUP BY post_cat ORDER BY id DESC LIMIT 10

3 个答案:

答案 0 :(得分:1)

我会保持简单并使用触发器来维护类别表中的last_post_id,这样您就可以轻松地重新加入帖子表 - 就像这样:

简单查询

select
 pc.cat_id,
 pc.name,
 u.username,
 bp.*
from
 post_category pc
inner join blog_post bp on pc.last_post_id = bp.post_id
inner join users u on bp.user_id = u.user_id
order by
 pc.cat_id;

+--------+------+----------+---------+---------+---------------------+
| cat_id | name | username | post_id | user_id | post_date           |
+--------+------+----------+---------+---------+---------------------+
|      1 | cat1 | bar      |       3 |       2 | 2011-02-09 12:45:33 |
|      2 | cat2 | BAR      |       5 |       3 | 2011-02-09 12:45:33 |
|      3 | cat3 | f00      |       4 |       1 | 2011-02-09 12:45:33 |
+--------+------+----------+---------+---------+---------------------+

drop table if exists post_category;
create table post_category
(
cat_id smallint unsigned not null auto_increment primary key,
name varchar(255) unique not null,
last_post_id int unsigned null,
key (last_post_id)
)
engine=innodb;

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varbinary(32) unique not null
)
engine=innodb;

drop table if exists blog_post;
create table blog_post
(
post_id int unsigned not null auto_increment primary key,
user_id int unsigned not null,
post_date datetime not null,
key (post_date, user_id)
)
engine=innodb;

drop table if exists blog_post_category;
create table blog_post_category
(
cat_id smallint unsigned not null,
post_id int unsigned not null,
primary key (cat_id, post_id)
)
engine=innodb;

触发器

delimiter #

create trigger blog_post_before_ins_trig before insert on blog_post
for each row
begin
  set new.post_date = now();
end#

create trigger blog_post_category_before_ins_trig before insert on blog_post_category
for each row
begin
  update post_category set last_post_id = new.post_id where cat_id = new.cat_id;
end#

delimiter ;

测试数据

insert into post_category (name) values ('cat1'),('cat2'),('cat3'),('cat4');
insert into users (username) values ('f00'),('bar'),('BAR'),('alpha'),('beta');

insert into blog_post (user_id) values (1),(1),(2),(1),(3);
insert into blog_post_category (cat_id, post_id) values
(1,1),(1,3),
(2,1),(2,5),
(3,1),(3,3),(3,4);

希望这会有所帮助:)

答案 1 :(得分:0)

答案 2 :(得分:0)

如果您只有三个类别,则可以单独进行查询并获取联合:

(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category1' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category2' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category3' ORDER BY `id` DESC LIMIT 10)

你甚至可以在最后重新整理整个事情。它只有30行!

SELECT * FROM (
    (SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category1' ORDER BY `id` DESC LIMIT 10) UNION
    (SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category2' ORDER BY `id` DESC LIMIT 10) UNION
    (SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category3' ORDER BY `id` DESC LIMIT 10)
) `monster` ORDER BY `id` DESC