如何选择具有最新日期的行并根据该行计算另一个字段

Posted

技术标签:

【中文标题】如何选择具有最新日期的行并根据该行计算另一个字段【英文标题】:How to select rows with the latest date and calculate another field based on the row 【发布时间】:2021-01-25 12:03:31 【问题描述】:

我有两个表,即车辆和车辆维护。

车辆

 -----------------------------------
|   v_id    |   v_name  |   v_no    |   
 -----------------------------------
|   1       |   car1    |   car123  |
 -----------------------------------
|   2       |   car2    |   car456  |
 -----------------------------------

车辆维护

 -----------------------------------------------------------------------
|   v_main_id   |   v_id    |   v_main_date     |   v_main_remainder    |   
 -----------------------------------------------------------------------
|       1       |   1       |   2020/10/10      |       1               |
|       2       |   1       |   2020/10/20      |       2               |
|       3       |   2       |   2020/10/04      |       365             |
|       4       |   2       |   2020/10/15      |       5               |
 -----------------------------------------------------------------------

我想获取每辆汽车的维护详细信息,即 car2 维护日期是 2020/10/15,我想根据 v_main_remainder 字段检查下一个维护日期。这意味着下一个维护日期将是 2020/10/20(维护日期增加 5 天)。我还想计算下一个维护日期的剩余天数。假设今天是 2020/10/10,那么它会显示还剩 10 天。

这是我的查询

SELECT
    v.v_id, 
    v.v_name, 
    v.v_no, 
    max(vm.v_main_date) as renewal_date,
    datediff(
        DATE_ADD(
            max(vm.v_main_date), INTERVAL +vm.v_main_remainder day
        ), 
        now()
    ) as day_left
    
FROM    vehicle as v, vehicle_maintenance as vm
GROUP BY v.v_id

但问题是从第一行获取的 date_add 函数中的 vm.v_main_remainder。

这是结果

 -----------------------------------------------------------------------
|   v_id    |   v_name  |   v_no    |   renewal_date    |   day_left    |
 -----------------------------------------------------------------------
|   1       |   car1    |   car123  |   2020/10/20      |       11      |
 -----------------------------------------------------------------------
|   2       |   car2    |   car456  |   2020/10/15      |       370     |
 -----------------------------------------------------------------------

【问题讨论】:

【参考方案1】:

首先,您的查询显然缺少两个表之间的连接条件,因此这是一个笛卡尔积。使用显式连接时,这类问题更容易被发现。

那么:你想过滤每辆车的最新维修记录,所以聚合是不合适的。

一个选项使用窗口函数,在 mysql 8.0 中可用:

select v.v_id, v.v_name, v.v_no, vm.v_main_date as renewal_date,
    datediff(vm.v_main_date + interval vm.v_main_remainder day, current_date) as day_left
from vehicle as v
inner join (
    select vm.*, row_number() over(partition by v_id order by v_main_date desc) rn
    from vehicle_maintenance
) as vm on vm.v_id = v.v_id
where vm.rn = 1

请注意,我将now() 更改为current_date,因此datediff()dates 而不是datetimes 上始终有效。

【讨论】:

感谢您的回答。我必须先了解它。让你知道。

以上是关于如何选择具有最新日期的行并根据该行计算另一个字段的主要内容,如果未能解决你的问题,请参考以下文章

根据可以具有值或为空的字段选择组内的行

根据另一列的字段值选择具有相同列值的行

如何为每个键值选择具有最新时间戳的行?

从每组中的 3 个表中选择 sql 中具有最新日期的行

用于从表中选择具有最新时间戳的行的 JOOQ 代码

查找具有延期日期范围的行并累积其持续时间