大家好。我相信这是一个“每组最多”的问题,但即使在查看了 StackOverflow 上的几个问题之后,我也不确定如何将其应用到我的情况中......
我正在使用 MySQL 数据库并设置了一个关于计算机应用程序的基本博客类型系统...表格如下所示:
POSTS
post_id
post_created
post_type -- could be article, review, feature, whatever
post_status -- 'a' approved or 'd' for draft
APPS
app_id
app_name
app_platform -- Windows, linux, unix, etc..
APP_TO_POST -- links my posts to its relevant application
atp_id
atp_app_id
atp_post_id
我正在使用以下基本查询来提取名称为“Photoshop”的应用程序的所有文章,其中帖子类型为“文章”且文章状态为“a”,表示已批准:
SELECT apps.app_name, apps.app_platform, posts.post_created, posts.post_id
FROM apps
JOIN app_to_post ON app_to_post.atp_app_id = apps.app_id
JOIN posts ON app_to_post.atp_post_id = posts.post_id
WHERE apps.app_name = 'Photoshop'
AND
posts.post_type = 'Article'
AND
posts.post_status = 'a'
这让我得到了这些预期的结果:
app_name app_platform post_created post_id
Photoshop Windows Oct. 20th, 2009 1
Photoshop Windows Dec. 1, 2009 3
Photoshop Macintosh Nov. 10th, 2009 2
谁能帮助我如何更改该查询以仅提取每个应用程序平台的最新文章?因此,例如,我希望我的结果如下所示:
app_name app_platform post_created post_id
Photoshop Windows Dec. 1, 2009 3
Photoshop Macintosh Nov. 10th, 2009 2
并省略其中一篇 'Photoshop Windows'
文章,因为它不是最新的。
如果我简单地添加一个 MAX(post_created)
和一个 GROUP BY app_platform
,我的结果并不总是正确分组。根据我的理解,我需要执行某种子查询的内部连接?
最佳答案
因为你有很多JOIN
,我建议先创建一个VIEW
:
CREATE VIEW articles AS
SELECT a.app_name, a.app_platform, p.post_created, p.post_id
FROM apps a
JOIN app_to_post ap ON ap.atp_app_id = a.app_id
JOIN posts p ON ap.atp_post_id = p.post_id
WHERE p.post_type = 'Article' AND p.post_status = 'a';
然后你可以使用 NULL-self-join:
SELECT a1.app_name, a1.app_platform, a1.post_created, a1.post_id
FROM articles a1
LEFT JOIN articles a2 ON
a2.app_platform = a1.app_platform AND a2.post_created > a1.post_created
WHERE a2.post_id IS NULL;
测试用例:
CREATE TABLE posts (
post_id int,
post_created datetime,
post_type varchar(30),
post_status char(1)
);
CREATE TABLE apps (
app_id int,
app_name varchar(40),
app_platform varchar(40)
);
CREATE TABLE app_to_post (
atp_id int,
atp_app_id int,
atp_post_id int
);
INSERT INTO posts VALUES (1, '2010-10-06 05:00:00', 'Article', 'a');
INSERT INTO posts VALUES (2, '2010-10-06 06:00:00', 'Article', 'a');
INSERT INTO posts VALUES (3, '2010-10-06 07:00:00', 'Article', 'a');
INSERT INTO posts VALUES (4, '2010-10-06 08:00:00', 'Article', 'a');
INSERT INTO posts VALUES (5, '2010-10-06 09:00:00', 'Article', 'a');
INSERT INTO apps VALUES (1, 'Photoshop', 'Windows');
INSERT INTO apps VALUES (2, 'Photoshop', 'Macintosh');
INSERT INTO app_to_post VALUES (1, 1, 1);
INSERT INTO app_to_post VALUES (1, 1, 2);
INSERT INTO app_to_post VALUES (1, 2, 3);
INSERT INTO app_to_post VALUES (1, 2, 4);
INSERT INTO app_to_post VALUES (1, 1, 5);
结果:
+-----------+--------------+---------------------+---------+
| app_name | app_platform | post_created | post_id |
+-----------+--------------+---------------------+---------+
| Photoshop | Macintosh | 2010-10-06 08:00:00 | 4 |
| Photoshop | Windows | 2010-10-06 09:00:00 | 5 |
+-----------+--------------+---------------------+---------+
2 rows in set (0.00 sec)
作为旁注,通常您不需要 surrogate key为您的junction table .您不妨设置一个复合主键(最好是引用表的外键):
CREATE TABLE app_to_post (
atp_app_id int,
atp_post_id int,
PRIMARY KEY (atp_app_id, atp_post_id),
FOREIGN KEY (atp_app_id) REFERENCES apps (app_id),
FOREIGN KEY (atp_post_id) REFERENCES posts (post_id)
) ENGINE=INNODB;
关于sql - MySQL greatest-n-per-group 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3869571/