尽量避免循环写sql,row_number 实际基本应用
一、原来sql
java
// 原来是 t1 表和t2 表关联,查t1的code,同时要是t2 表某个属性xx 降序后取一个
String sql =" SELECT t1.*, t2.xx, " +
" FROM table1 t1 " +
" LEFT JOIN table2 t2 ON t1.id = t2.table1_id " +
" WHERE t1.code = '{}' order by t2.xx desc fetch first 1 rows only ";
// 在循环中写sql
for(YourObject item : objectList){
String code = item.getCode();
Map<Stirng,Object> resultMap = getSqlMapper().selectOne(strUtil.format(sql,code));
// 查出结果继续别的处理
}
二、优化后sql
java
public void processWithRowNumber(List<YourObject> objectList) {
if (objectList.isEmpty()) return;
Set<Long> codeSet = objectList.stream()
.map(YourObject::getCode)
.collect(Collectors.toSet());
String inClause = codeSet.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
// 使用ROW_NUMBER()为每个ID分组,取最新的一条
String sql = "SELECT * FROM (" +
" SELECT t1.*, t2.xx, " +
" ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.xx DESC) as rn " +
" FROM table1 t1 " +
" LEFT JOIN table2 t2 ON t1.id = t2.table1_id " +
" WHERE t1.code IN (" + inClause + ")" +
") WHERE rn = 1";
List<Map<String, Object>> results = sqlMapper.selectList(sql);
// 构建映射关系
Map<Long, Map<String, Object>> resultMap = results.stream()
.collect(Collectors.toMap(
result -> ((Number) result.get("CODE")).longValue(),
result -> result
));
// 处理结果
for (YourObject obj : objectList) {
Map<String, Object> result = resultMap.get(obj.getCode());
if (result != null) {
processSingleResult(obj, result);
}
}
}
三、总结
这是row_number 实际基本应用(用于优化sql放在循环外)
将sql拿出循环就是 用row_number() over()原因
之前博客记录 row_number用法 Row number 函数用法
实际项目使用过 row_number 实际基本应用