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

如何用Diesel 2.x ORM实现分组查询最新数据行?

在Diesel 2.x中实现按组查询最新数据行

常见的SQL需求是查询每组的最新数据行,比如下面的SQL可以获取每个用户的最新余额:

SELECT user, date, balance
FROM balances t1
INNER JOIN (
    SELECT user, max(date) as most_recent_date
    FROM balances
    GROUP BY user
) t2
    ON t1.user=t2.user AND t1.date=t2.most_recent_date

方案1:模拟原SQL的关联子查询

你可以通过给子查询字段添加别名,让Diesel能够识别并关联子查询与原表。步骤如下:

  1. 构造子查询并给聚合字段起别名
  2. 使用inner_join关联原表与子查询,明确关联条件

示例代码:

use diesel::prelude::*;
use diesel::dsl::max;
use diesel::alias;

// 给子查询定义别名,方便后续引用字段
let t2 = alias!(t2);

// 构造子查询:获取每个用户的最新日期
let latest_dates = balances::table
    .group_by(balances::user)
    .select((
        balances::user.as(t2.user),
        max(balances::date).as(t2.most_recent_date),
    ));

// 关联原表与子查询,筛选出最新的余额记录
let latest_balances = balances::table
    .inner_join(latest_dates.on(
        balances::user.eq(t2.user)
            .and(balances::date.eq(t2.most_recent_date))
    ))
    .select((balances::user, balances::date, balances::balance))
    .load::<(i32, NaiveDateTime, f64)>(&conn)?;

方案2:使用窗口函数(更简洁高效)

另一种更优雅的方式是利用窗口函数row_number(),按用户分组并按日期降序排序,取每组的第一行数据,逻辑上和原SQL完全一致:

use diesel::prelude::*;
use diesel::dsl::{row_number, over, partition_by, desc};

// 给每条记录添加分组内的排名,日期越新排名越靠前
let ranked_records = balances::table
    .select((
        balances::user,
        balances::date,
        balances::balance,
        row_number()
            .over(partition_by(balances::user).order_by(desc(balances::date)))
            .alias("rn"),
    ))
    .into_boxed();

// 筛选出每组排名第一的记录(即最新数据)
let latest_balances = ranked_records
    .filter(ranked_records.field("rn").eq(1))
    .select((balances::user, balances::date, balances::balance))
    .load::<YourBalanceStruct>(&conn)?;

关键说明

你之前遇到的问题是因为子查询的字段没有明确的别名映射,Diesel需要清晰的字段标识才能在关联时匹配原表字段。上面两种方案都不需要编写原生SQL,完全基于Diesel的DSL实现,且功能与目标SQL一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:57:23