在MyBatis-Plus中,Sum函数是用于实现聚合查询的核心功能之一,常用于统计数值型字段的总和(如订单金额、用户积分等)。本文ZHANID工具网将详细讲解Sum函数的使用方法,结合QueryWrapper和LambdaQueryWrapper两种方式,并提供完整示例代码。
一、Sum函数基础用法
1. 使用QueryWrapper实现Sum查询
场景:统计order表中所有订单的amount字段总和。
代码示例:
// 创建QueryWrapper
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
queryWrapper.select("SUM(amount) as totalAmount");
// 执行查询
List<Map<String, Object>> result = orderMapper.selectMaps(queryWrapper);
// 解析结果
BigDecimal totalAmount = (BigDecimal) result.get(0).get("totalAmount");
System.out.println("总金额: " + totalAmount);关键点:
select("SUM(amount) as totalAmount"):指定聚合函数并设置别名。selectMaps():返回List<Map>,需通过别名提取结果。默认返回
BigDecimal类型,避免精度丢失。
2. 使用LambdaQueryWrapper实现Sum查询
场景:统计满足条件的订单总金额(如状态为已支付的订单)。
代码示例:
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(Order::getAmount, Order::getStatus)
.eq(Order::getStatus, "PAID")
.select("SUM(amount) as totalAmount");
List<Map<String, Object>> result = orderMapper.selectMaps(lambdaWrapper);
BigDecimal paidTotal = (BigDecimal) result.get(0).get("totalAmount");优势:
使用Lambda表达式避免硬编码字段名,提升代码可读性。
支持链式调用,可组合多个查询条件。
二、Sum函数结合分组(GROUP BY)
场景:按用户ID统计订单总金额,并筛选总金额大于1000的用户。
代码示例:
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(Order::getUserId, "SUM(amount) as totalAmount")
.groupBy(Order::getUserId)
.having("SUM(amount) > {0}", 1000);
List<Map<String, Object>> result = orderMapper.selectMaps(lambdaWrapper);
result.forEach(item -> {
Long userId = (Long) item.get("userId");
BigDecimal total = (BigDecimal) item.get("totalAmount");
System.out.println("用户" + userId + "总金额: " + total);
});关键点:
groupBy():指定分组字段。having():过滤分组后的结果(支持参数占位符{0})。
三、Sum函数结合排序(ORDER BY)
场景:统计各商品类别的销售额,并按总销售额降序排列。
代码示例:
LambdaQueryWrapper<Product> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(Product::getCategoryId, "SUM(price * stock) as totalSales")
.groupBy(Product::getCategoryId)
.orderByDesc("totalSales");
List<Map<String, Object>> result = productMapper.selectMaps(lambdaWrapper);
result.forEach(item -> {
Long categoryId = (Long) item.get("categoryId");
BigDecimal sales = (BigDecimal) item.get("totalSales");
System.out.println("分类" + categoryId + "销售额: " + sales);
});说明:
orderByDesc("totalSales"):按聚合结果排序(需使用别名)。
四、Service层封装示例
推荐做法:在Service层封装通用聚合查询方法。
代码示例:
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
public BigDecimal calculateTotalAmount(String status) {
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
wrapper.select(Order::getAmount)
.eq(Order::getStatus, status)
.select("SUM(amount) as totalAmount");
List<Map<String, Object>> result = orderMapper.selectMaps(wrapper);
if (result.isEmpty() || result.get(0).get("totalAmount") == null) {
return BigDecimal.ZERO;
}
return (BigDecimal) result.get(0).get("totalAmount");
}
}调用示例:
// 统计所有已支付订单总金额
BigDecimal total = orderService.calculateTotalAmount("PAID");
System.out.println("已支付总金额: " + total);
五、高级用法:多字段聚合查询
场景:同时统计订单数、总金额和平均金额。
代码示例:
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(
"COUNT(*) as orderCount",
"SUM(amount) as totalAmount",
"AVG(amount) as avgAmount"
)
.eq(Order::getStatus, "PAID");
List<Map<String, Object>> result = orderMapper.selectMaps(lambdaWrapper);
Map<String, Object> stats = result.get(0);
System.out.println("订单数: " + stats.get("orderCount"));
System.out.println("总金额: " + stats.get("totalAmount"));
System.out.println("平均金额: " + stats.get("avgAmount"));六、注意事项
字段别名:
使用select("SUM(amount) as totalAmount")必须指定别名,否则无法通过Map键获取结果。空值处理:
当查询无结果时,result.get(0)可能为null,需做空指针判断。类型安全:
返回的数值类型默认为BigDecimal,避免使用Double导致精度丢失。性能优化:
对大数据量表使用聚合查询时,建议添加必要的索引(如分组字段、过滤字段)。
七、完整示例代码结构
src/ ├── main/ │ ├── java/ │ │ └── com/example/ │ │ ├── entity/Order.java │ │ ├── mapper/OrderMapper.java │ │ ├── service/OrderService.java │ │ └── controller/OrderController.java
Order实体类:
@Data
@TableName("t_order")
public class Order {
private Long id;
private Long userId;
private BigDecimal amount;
private String status;
private Date createTime;
}OrderMapper接口:
public interface OrderMapper extends BaseMapper<Order> {
// 继承BaseMapper即可,无需额外方法
}八、总结
MyBatis-Plus通过QueryWrapper和LambdaQueryWrapper提供了灵活的Sum函数使用方式,核心步骤包括:
使用
select()指定聚合函数及别名。通过
groupBy()/having()/orderBy()实现复杂统计。在Service层封装通用方法提升复用性。
合理使用聚合查询可大幅提升数据统计效率,结合索引优化能应对百万级数据量的统计需求。实际开发中建议优先使用LambdaQueryWrapper以规避字段名硬编码风险。
本文由@战地网 原创发布。
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/4617.html




















