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

SQL多表查询:获取每个主表记录对应的从表最新单条数据

解决方案

你遇到的是典型的「分组取最新/第一条」场景,原写法的问题在于用了全局LIMIT,只会对整个结果集做条数截断,无法按关联的外键分组分别取数,以下是可直接使用的实现方式:


1. 主流数据库通用写法(支持MySQL 8.0+、PostgreSQL、SQL Server、SQLite 3.25+等所有支持窗口函数的版本)

用窗口函数ROW_NUMBER()按外键分区、按时间倒序排序,筛选每个分区序号为1的记录即可,性能远好于子查询关联写法:

SELECT t2.*
FROM (
    SELECT
        *,
        ROW_NUMBER() OVER (PARTITION BY fk ORDER BY time DESC) AS row_num
    FROM tbl2
    WHERE fk IN (SELECT id FROM tbl1 WHERE some_criteria)
) t2
WHERE t2.row_num = 1;
  • 注意:如果同一外键fk下存在多条time完全相同的记录,上述语句会随机返回其中一条;如果需要把同时间的所有记录都返回,把ROW_NUMBER()替换为RANK()即可。

如果需要保留tbl1中没有对应tbl2匹配记录的条目(即tbl2关联0条记录时也返回tbl1内容,对应tbl2字段显示NULL),使用左连接写法:

SELECT t1.*, t2.*
FROM (SELECT * FROM tbl1 WHERE some_criteria) t1
LEFT JOIN (
    SELECT
        *,
        ROW_NUMBER() OVER (PARTITION BY fk ORDER BY time DESC) AS row_num
    FROM tbl2
) t2 ON t1.id = t2.fk AND t2.row_num = 1;

2. 老版本数据库兼容写法(不支持窗口函数,如MySQL 5.x)

先按外键分组取出每个外键对应的最大时间,再关联回tbl2取出对应记录的全部字段:

SELECT t2.*
FROM tbl2 t2
INNER JOIN (
    SELECT fk, MAX(time) AS latest_time
    FROM tbl2
    WHERE fk IN (SELECT id FROM tbl1 WHERE some_criteria)
    GROUP BY fk
) t2_latest ON t2.fk = t2_latest.fk AND t2.time = t2_latest.latest_time;
  • 注意:该写法如果遇到同一外键下多条记录时间等于最大时间的情况,会把这些记录全部返回。

原写法问题说明

  • 带LIMIT 1的写法:全局限制结果集仅返回1条,自然无法覆盖所有符合条件的tbl1记录
  • 仅做时间倒序的写法:没有按外键分组做条数截断,会返回所有匹配的tbl2记录,无法实现单条tbl1对应单条最新tbl2记录的要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:09:18