在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