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

MySQL左关联获取最新右表记录,无数据时显示NULL

解决方案:获取左表全量记录并关联右表最新数据

原查询问题分析

你的原查询存在两处关键问题:

  1. 关联tally表时使用了未定义的别名tb(子查询内的别名无法作用到外层连接条件);
  2. 子查询的逻辑错误,导致左连接的过滤条件变相成为内连接规则,丢失了无关联记录的bill行(比如billId=1)。

正确实现(MySQL 8.0+ 窗口函数方案)

利用MySQL 8.0支持的ROW_NUMBER()窗口函数,可以高效筛选每个bill对应的最新tally记录,同时保证左表全量输出:

WITH ranked_tallies AS (
    SELECT
        tb.billId,
        t.countYes,
        t.countNo,
        -- 按bill分组,每组内按创建时间倒序排名,最新记录排第1
        ROW_NUMBER() OVER (PARTITION BY tb.billId ORDER BY t.created DESC) AS rn
    FROM tally_bill tb
    JOIN tally t ON tb.tallyId = t.id
)
SELECT
    b.id AS billId,
    b.description,
    b.extId,
    rt.countYes,
    rt.countNo
FROM bill b
LEFT JOIN ranked_tallies rt ON b.id = rt.billId AND rt.rn = 1;

逻辑说明

  1. CTE子查询(ranked_tallies):
    • 关联中间表tally_bill和数据tally表,获取所有bill对应的tally记录;
    • 通过窗口函数ROW_NUMBER()给每个bill分组内的tally记录按created降序排名,最新的记录会被标记为rn=1。
  2. 主查询:
    • 从bill表左连接到CTE结果,只匹配排名为1的记录(即每个bill的最新tally数据);
    • 左连接保证即使没有对应tally记录的bill(比如id=1)也会保留在结果中,对应的统计字段自动填充为NULL。

结果验证

执行上述查询后,会得到与你期望完全一致的输出:

billId    description    extId    countYes    countNo
1         Some descr...  SB 123   null        null
2         Another de...  SB 124   5           8
3         Third desc...  SB 125   4           3

兼容写法(无CTE版本)

如果不习惯使用CTE,也可以将逻辑嵌套为子查询:

SELECT
    b.id AS billId,
    b.description,
    b.extId,
    rt.countYes,
    rt.countNo
FROM bill b
LEFT JOIN (
    SELECT
        tb.billId,
        t.countYes,
        t.countNo,
        ROW_NUMBER() OVER (PARTITION BY tb.billId ORDER BY t.created DESC) AS rn
    FROM tally_bill tb
    JOIN tally t ON tb.tallyId = t.id
) rt ON b.id = rt.billId AND rt.rn = 1;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:45:43