聚合函数:SUM / AVG / MIN / MAX

聚合通过 `linq!` 宏的 `sum` / `avg` / `min` / `max` 子句表达。列字段在闭包中以 `i.amount` 形式访问(编译期解析为 `OrderItem::COLUMN_AMOUNT` 常量)。

基本用法

// sum / avg 返回 f64
let total_sales: f64 = linq!(ctx.set::<OrderItem>(); sum i.amount).await?;
let avg_price: f64 = linq!(ctx.set::<OrderItem>(); avg i.price).await?;

// min / max 返回 Option<V>,类型由调用点推断(G1 修复后保留原类型)
let min_price: f64 = linq!(ctx.set::<OrderItem>(); min i.price).await?.unwrap_or(0.0);
let max_price: f64 = linq!(ctx.set::<OrderItem>(); max i.price).await?.unwrap_or(0.0);

// 跨类型推断:i32 列赋给 i64 变量
let max_qty: i64 = linq!(ctx.set::<OrderItem>(); max i.quantity).await?.unwrap_or(0);

带过滤的聚合

// linq! 多子句形式:过滤 + 聚合终端
let filtered_sum: f64 = linq!(ctx.set::<OrderItem>(), |i: OrderItem| i.category_id == target_cat;
    sum i.amount
).await?;

空集语义

- `sum` / `avg` 对空表返回 `0.0` - `min` / `max` 对空表返回 `Ok(None)`(SQL NULL 经 `convert_aggregate_cell` 转换为 `None`)

性能注意

- 聚合在**数据库端**执行,只返回一个标量值,比加载全部行再内存求和高效得多 - `min` / `max` 通过 `TryFrom<DbValue>` 在调用点保留原类型,无需手动 `parse`

设计要点

| 实践 | 说明 | |------|------| | 聚合前先用 `linq!` 过滤 | 减少扫描的数据量 | | 不需要实体物化时优先用聚合 | 避免 `to_list()` 的内存和序列化开销 | | `min`/`max` 类型由调用点推断 | 用 `let v: i64 = linq!(...; max b.col).await?.unwrap_or(0);` 显式标注 |

下一节:[GROUP BY 与 HAVING](group-by-having.md)