sql - MySQL greatest-n-per-group 问题

标签 sql mysql database greatest-n-per-group

大家好。我相信这是一个“每组最多”的问题,但即使在查看了 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/

相关文章:

javascript - Sails.js 上传后如何获取图像的名称

mysql - Django MySQL 第 1 行第 'telephone' 列的值超出范围

php - PDO 和 MySQL 'max_user_connections'

sql - sql server中如何对字符串进行排序

mysql - 使用 'Index' 还是使用查询在相关数据库列之间创建连接更好?

java - 如何使用 JOOQ 从模板和参数占位符生成 sql?

SQL 查找平均元组数(既不是最大值也不是最小值)

sql - MySQL - 限制连接中的行数?

.net - 数据库表复制指南

sql - EntityFramework,不存在则插入,否则更新