mysql in查詢 結果亂序 引發的思考


Mysql in查詢 結果集 亂序 

SQL: select * from table where id IN (3,6,9,1,2,5,8,7);

這樣的情況取出來后,其實,id還是按1,2,3,4,5,6,7,8,9,排序的,但如果我們真要按IN里面的順序排序怎么辦?SQL能不能完成?是否需要取回來后再foreach一下?其實mysql就有這個方法

sql: select * from table where id IN (3,6,9,1,2,5,8,7) order by field(id,3,6,9,1,2,5,8,7); 

出來的順序就是指定的順序了。。。。

 

寫法二:  select * from table where id in ( 3,6,9,1,2,5,8,7 ) order by find_in_set(id,' 3,6,9,1,2,5,8,7 ');

 但是這么寫 explain  select * from table where id IN (3,6,9,1,2,5,8,7) order by field(id,3,6,9,1,2,5,8,7); 

會Using filesort  導致查詢效率降低  

所以可以這樣  把結果集查詢出來 自己sort

List<Employee> employees = new ArrayList<>();
employees.add(new Employee(123, "Jack", "Johnson", LocalDate.of(1988, Month.APRIL, 12)));
employees.add(new Employee(345, "Cindy", "Bower", LocalDate.of(2011, Month.DECEMBER, 15)));
employees.add(new Employee(567, "Perry", "Node", LocalDate.of(2005, Month.JUNE, 07)));
employees.add(new Employee(467, "Pam", "Krauss", LocalDate.of(2005, Month.JUNE, 07)));
employees.add(new Employee(435, "Fred", "Shak", LocalDate.of(1988, Month.APRIL, 17)));
employees.add(new Employee(678, "Ann", "Lee", LocalDate.of(2007, Month.APRIL, 12)));

employees=employees.stream().sorted((e1, e2) -> e1.getHireDate().compareTo(e2.getHireDate())).collect(Collectors.toList());


接着:

 

描述下問題的由來

 

 存在條件:

 1. 有一個合輯表 A, 有一個內容表 C.   C表中有一個列a_id 關聯兩個表 

 2. A表中有3000條數據 C表中有2w條數據  合輯表中有的有內容 有的沒有內容

需求:
 1. 分頁顯示合輯列表, 每個合輯有個ContentSize字段 表示合輯的內容數量.

 

解析步驟:

  分兩次查詢: 第一次查分頁. 第二次查合輯的內容數量.

1.分頁sql 忽略.

2.統計list<合輯id> 合輯id列表中的 每合輯對應的內容數量

當時想到了第一種方式  連接查詢 count in group by  order by id的順序  (次方法有兩點不好1. left join 連表 效率低 2. 結果集順序 Using filesort 效率低) 

@Query(value = "select count(c.id) from abm_album a left join  abm_album_content c  on a.id=c.album_id and c.is_deleted =:isDeleted  where a.id in (:albumIds) group by a.id  order by field(a.id,:albumIds) ",nativeQuery = true)
public List<BigInteger> countByAlbumIdsAndIsDeleted(@Param("isDeleted")Integer isDeleted,@Param("albumIds")List<Integer> albumIds);
---------------------------方式一:解析SQL如下-------------------------
select
count(c.id)
from
abm_album a left join abm_album_content c
on a.id=c.album_id and c.is_deleted =0
where
a.id in (5138822,5160757,5000142,5160750,5159885)
group by a.id
order by field(a.id,5138822,5160757,5000142,5160750,5159885)
@Query(value = "select c.album_id ,count(c.id) from  abm_album_content c  where  c.is_deleted =:isDeleted  and c.album_id in (:albumIds) group by c.album_id ",nativeQuery = true)
public List<Object[]> countMapByAlbumIdsAndIsDeleted(@Param("isDeleted")Integer isDeleted,@Param("albumIds")List<Integer> albumIds);
---------------------------方式二:解析SQL如下-------------------------
select
c.album_id , count(c.id)
from abm_album_content c
where
c.is_deleted =0
and c.album_id in (5138822,5160757,5000142,5160750,5159885 )
group by c.album_id

---------------------------查詢結果處理-------------------------
List<Album> datas = albumRepository.find(album, page.getStart(), page.getPageSize(), sort);
if(null!=datas && datas.size()>0){
//設置稿件數量
try {
List<Integer> ids= datas.stream().map(Album::getId).collect(Collectors.toList());
// 方式一 list查詢 in帶順序 然后順序set sql關聯查詢 執行效率低
/*
List<BigInteger> bigIntegers = albumContentRepository.countByAlbumIdsAndIsDeleted(AlbumConstant.UNDELETED, ids);
if(datas.size()==ids.size()&&datas.size()==bigIntegers.size()){
for (int i=0;i<datas.size();i++){
datas.get(i).setContentsCount(bigIntegers.get(i).intValue());
}
}
*/
// 方式二 執行單表count 返回值list<Object[]> 循環設置 效率高
List<Object[]> maps = albumContentRepository.countMapByAlbumIdsAndIsDeleted(AlbumConstant.UNDELETED, ids);
Map<Integer,BigInteger> countMap=new HashMap<>();
maps.forEach(map->countMap.put((Integer)map[0],(BigInteger)map[1]));
datas.forEach(data-> {
if(null!=countMap.get(data.getId())){
data.setContentsCount(countMap.get(data.getId()).intValue());
}else {
data.setContentsCount(0);
}
});
}catch (Exception e){
log.error("查詢合輯下稿件數量出錯",e);
}
}
//set結果集
page.setDatas(datas); 

總結:

1. in 查詢 返回的結果集 如果有數據不存在的時候 返回結果集的個數 和合輯id_list的size 是不一樣的. 

2. 能單表查詢 盡量不要鏈表查詢 

OK. 到此結束 小記...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM