从更优化的 2 个表中获取 MySQL 的最新记录 [重复]

Posted

技术标签:

【中文标题】从更优化的 2 个表中获取 MySQL 的最新记录 [重复]【英文标题】:Get the newest record from MySQL from 2 tables more optimalized [duplicate] 【发布时间】:2021-01-31 00:48:52 【问题描述】:

我在 SQL 中的查询有一些问题。 我有 2 张桌子。

people
    +----+--------+------+
    | id |  name  | val2 |
    +----+--------+------+
    |  1 | john   |   12 |
    |  2 | adam   |    5 |
    |  3 | alfred |    3 |
    +----+--------+------+

data
+----+----+----+-----+---------------------+
| id | v1 | v2 | v3  |        date         |
+----+----+----+-----+---------------------+
|  1 |  4 | 15 |  18 | 2020-10-16 11:15:53 |
|  1 |  2 | 12 |  17 | 2020-10-16 11:22:53 |
|  1 |  3 | 13 |  16 | 2020-10-16 11:32:53 |
|  2 |  1 | 16 |  15 | 2020-10-16 13:22:53 |
|  2 |  3 | 13 |  25 | 2020-10-16 13:42:53 |
|  2 |  4 | 12 |  35 | 2020-10-16 14:12:53 |
|  3 |  1 | 21 | 12  | 2020-10-16 14:12:53 |
|  3 |  2 | 28 | 42  | 2020-10-16 15:12:53 |
|  3 |  4 | 30 | 72  | 2020-10-16 16:12:53 |
+----+----+----+-----+---------------------+

我需要输入一个表 ID、NAME、v1、v2、v3、date 来获取第一个表中所有对象的新日期 像这样:

RESULT
+----+--------+----+----+-----+---------------------+
| id |  name  | v1 | v2 | v3  |        date         |
+----+--------+----+----+-----+---------------------+
|  1 | john   |  3 | 13 |  16 | 2020-10-16 11:32:53 |
|  2 | adam   |  4 | 12 |  35 | 2020-10-16 14:12:53 |
|  3 | alfred |  4 | 30 | 72  | 2020-10-16 16:12:53 |
+----+--------+----+----+-----+---------------------+

我需要第一个表中所有人的第二个表中的最新记录。 我尝试通过这个查询来做到这一点:

SELECT people.id,
   people.name,
   data.v1,
   data.v2,
   data.v3,
   max(data.date)
FROM people
JOIN DATA ON people.id = data.id
GROUP BY people.id

我得到了最新的数据,但 v1、v2、v3 是从表中随机得出的。

【问题讨论】:

【参考方案1】:

您想要来自data 的整行,因此这里不能选择聚合。在大多数数据库中,您的查询会失败,因为selectgroup by 子句不一致……但是,不幸的是,mysql 为您提供了足够的绳索让开发人员上吊。您的查询运行(如果 sql 模式 ONLY_FULL_GROUP_BY 被禁用),但实际上相当于:

SELECT people.id, people.name, ANY_VALUE(data.v1), ANY_VALUE(data.v2), ANY_VALUE(data.v3), MAX(data.date)
FROM people
JOIN data on people.id = data.id
GROUP BY people.id

现在很明显,数据库为您提供了 任何值 data 与连接条件匹配的行 - 这可能属于也可能不属于具有最新日期的行。

您实际上需要过滤而不是分组。一种选择使用子查询:

select p.id, p.name, d.v1, d.v2, d.v3, d.date
from people p
inner join data d on d.id = p.id
where d.date = (select max(d1.date) from data d1 where d1.id = d.id)

这种方法的好处是它适用于所有版本的 MySQL,包括 8.0 之前的版本,其中窗口函数不可用。

【讨论】:

有没有可能让这个 Select 更加优化?【参考方案2】:

一个简单的方法使用窗口函数:

SELECT p.id, p.name, d.v1, d.v2, d.v3, d.date)
FROM people p JOIN
     (SELECT d.*,
             ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY d.date DESC) as seqnum
      FROM data d
     ) d
     ON p.id = d.id AND d.seqnum = 1;

注意:data 中的连接列是 id 似乎很奇怪。我希望它被称为people_id

【讨论】:

以上是关于从更优化的 2 个表中获取 MySQL 的最新记录 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

优化查询以获取日志表中每个人的最新记录

从 2 个表中获取记录数 - 一对多关系

如何从 MySQL (MardiaDB) 依赖表中的最新记录中获取信息?

优化查询以从不同的表中获取唯一(用户)记录

MySQL SQL 获取表中的最新记录?

对第二个表中不存在 ID 的两个表的 MySQL 查询优化