You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL分组排序问题:无法生成目标查询结果求助

MySQL查询获取分组最新记录问题

我现在需要编写一条MySQL查询语句来生成指定格式的输出,但试了好几条查询都没成功。

实际数据情况

我的数据是关联了vendor_charge、vendor_charge_details和charges三张表的结果,其中存在同一charge_id+per+currency组合下有多条不同effective_date的记录,且这些记录都满足vendor_id='12'和effective_date <= '2018-05-22'的条件。

期望输出

我需要对每个charge_id+per+currency的组合,只保留**effective_date最新(最大)**的那条完整记录,也就是每个组合仅显示一条最新的条目。

已尝试的查询语句

我试过下面两条查询,但都没得到想要的结果:

第一条:

SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`, `VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks` 
FROM `vendor_charge` `VC` 
INNER JOIN `vendor_charge_details` `VCD` ON `VC`.`id` = `VCD`.`vc_id` 
LEFT JOIN `charges` `C` ON `C`.`id` = `VCD`.`charge_id` 
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22' 
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency` 
ORDER BY `C`.`head` DESC 

第二条:

SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`, `VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks` 
FROM `vendor_charge` `VC` 
INNER JOIN `vendor_charge_details` `VCD` ON `VC`.`id` = `VCD`.`vc_id` 
LEFT JOIN `charges` `C` ON `C`.`id` = `VCD`.`charge_id` 
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22' 
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency` 
ORDER BY `VCD`.`effective_date` DESC 

问题原因及解决方案

之前的查询用GROUP BY时,没有指定要获取每个分组里最新的那条记录——MySQL在使用GROUP BY但不对非分组字段用聚合函数时,会返回分组内的任意一条记录,而不是我们需要的最新日期的那条。

这里提供两种可行的解决方案:

方案1:子查询关联获取最新记录(兼容所有MySQL版本)

先找出每个分组对应的最大effective_date,再关联原表获取完整记录:

SELECT VCD.id, VCD.effective_date, VCD.charge_id, C.head, VCD.per, VCD.currency, VCD.amount, VCD.remarks
FROM vendor_charge VC
INNER JOIN vendor_charge_details VCD ON VC.id = VCD.vc_id
LEFT JOIN charges C ON C.id = VCD.charge_id
INNER JOIN (
    -- 先获取每个分组的最大effective_date
    SELECT charge_id, per, currency, MAX(effective_date) AS max_date
    FROM vendor_charge_details
    WHERE vc_id IN (SELECT id FROM vendor_charge WHERE vendor_id = '12')
      AND effective_date <= '2018-05-22'
    GROUP BY charge_id, per, currency
) AS latest ON VCD.charge_id = latest.charge_id 
           AND VCD.per = latest.per 
           AND VCD.currency = latest.currency 
           AND VCD.effective_date = latest.max_date
WHERE VC.vendor_id = '12'
ORDER BY C.head DESC;

方案2:窗口函数(MySQL 8.0及以上版本适用)

用ROW_NUMBER()窗口函数给每个分组的记录按日期排序,取排序第一的最新记录:

SELECT id, effective_date, charge_id, head, per, currency, amount, remarks
FROM (
    SELECT VCD.id, VCD.effective_date, VCD.charge_id, C.head, VCD.per, VCD.currency, VCD.amount, VCD.remarks,
           -- 按分组排序,最新的日期排第一
           ROW_NUMBER() OVER (PARTITION BY VCD.charge_id, VCD.per, VCD.currency ORDER BY VCD.effective_date DESC) AS rn
    FROM vendor_charge VC
    INNER JOIN vendor_charge_details VCD ON VC.id = VCD.vc_id
    LEFT JOIN charges C ON C.id = VCD.charge_id
    WHERE VC.vendor_id = '12' AND VCD.effective_date <= '2018-05-22'
) AS temp
WHERE rn = 1 -- 只取每个分组的第一条(最新的)
ORDER BY head DESC;

这两种方式都能准确获取到每个组合下最新的那条记录,符合期望输出。

内容的提问来源于stack exchange,提问作者user9879553

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:58:35