考試批次 | 班級 | 名稱 | 語言 |
---|---|---|---|
三年一班 | 張小明 | 130.00 | ##202302 |
王二小 | 128.00 | 202302 | |
#謝春花 | 136.00 | 202302 | |
馮世傑 | 129.00 | #202302 |
馬功成
130.00
202302
#三年二班
136.00
rank()涵數主要用於排序,並給出序號 ,對於排序並列的資料給予相同序號,並空出並列所佔的名次。 dense_rank() 功能同rank()一樣,差別在於不空出並列所佔的名次RANK() OVER(PARTITION BY COLUMN ORDER BY COLUMN) dense_rank() OVER(PARTITION BY COLUMN ORDER BY COLUMN) ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)解釋:partition by用於給結果集分組,如果沒有指定那麼它將整個結果集作為一個分組。
rank 結果為1,2,2,4 dense_rank 結果為1,2,2,3 row_number 結果為1,2 ,3,4
public class OrderBy { private String orderByEL; /** * 是否升序 */ private boolean ascend; public OrderBy(){ //默认升序 this.ascend = true; } public String orderByEL(){ return this.orderByEL; } public OrderBy orderByEL(String orderByEL){ this.orderByEL = orderByEL; return this; } public OrderBy ascend(boolean ascend){ this.ascend = ascend; return this; } public boolean ascend(){ return this.ascend; } }該類別定義瞭如下屬性: 排序的fileld 是否升序
<T> void rankOver(List<T> dataList, String[] partitionByFields, List<OrderBy> orderByList, String resultField, int rankType);
##orderByList 排序欄位集合
rankType 排名方式
#1:不考慮並列(row_number 結果為1,2,3,4)
2 :考慮並列,空出並列所佔的名次(rank 結果為1,2,2,4)
3:考慮並列,不空出並列所佔的名次(dense_rank 1,2,2,3)我們寫一個方法,返回以下數據:
此方法具體實作如下public static <T> void rankOver(List<T> dataList, String[] partitionByFields, List<OrderBy> orderByList, String resultField, int rankType) { if (CollectionUtils.isEmpty(orderByList)) { return; } //STEP_01 剔除掉不参与排名的数据 List<T> tempList = new ArrayList<>(); for (T data : dataList) { boolean part = true; for (OrderBy rptOrderBy : orderByList) { Object o1 = executeSpEL(rptOrderBy.orderByEL(), data); if (o1 == null) { //参与排序的值为null的话则不参与排名 part = false; break; } } if (part) { tempList.add(data); } } if (CollectionUtils.isEmpty(tempList)) { return; } //STEP_02 分组 Map<String, List<T>> groupMap = group(tempList, null, partitionByFields); for (List<T> groupDataList : groupMap.values()) { order(orderByList, groupDataList); if (rankType == 1) { int rank = 1; for (T temp : groupDataList) { setFieldValue(temp, resultField, rank); rank++; } } else { int prevRank = Integer.MIN_VALUE; int size = groupDataList.size(); for (int i = 0; i < size; i++) { T current = groupDataList.get(i); if (i == 0) { //第一名 setFieldValue(current, resultField, 1); prevRank = 1; } else { T prev = groupDataList.get(i - 1); boolean sameRankWithPrev = true;//并列排名 for (OrderBy rptOrderBy : orderByList) { Object o1 = executeSpEL(rptOrderBy.orderByEL(), current); Object o2 = executeSpEL(rptOrderBy.orderByEL(), prev); if (!o1.equals(o2)) { sameRankWithPrev = false; break; } } if (sameRankWithPrev) { setFieldValue(current, resultField, getFieldValue(prev, resultField)); if (rankType == 2) { ++prevRank; } } else { setFieldValue(current, resultField, ++prevRank); } } } } } }
使用案例
定義一個學生類別:public class Student { private String batch; private String banji; private String name; private Double yuwen; //extra private Integer rank1; private Integer rank2; public Student(String batch, String banji, String name, Double yuwen) { this.batch = batch; this.banji = banji; this.name = name; this.yuwen = yuwen; } }
public List<Student> getDataList() { List<Student> dataList = new ArrayList<>(); dataList.add(new Student("202302", "三年一班", "张小明", 130.0)); dataList.add(new Student("202302", "三年一班", "王二小", 128.0)); dataList.add(new Student("202302", "三年一班", "谢春花", 136.0)); dataList.add(new Student("202302", "三年二班", "冯世杰", 129.0)); dataList.add(new Student("202302", "三年二班", "马功成", 130.0)); dataList.add(new Student("202302", "三年二班", "魏翩翩", 136.0)); return dataList; }取得學生語言成績的班級排名和年段排名,排名採用並列並空出並列所佔用名次的方式。 ###
List<Student> dataList = getDataList(); List<OrderBy> orderByList = new ArrayList<>(); orderByList.add(new OrderBy().orderByEL("yuwen").ascend(false)); //获取全校排名 DataProcessUtil.rankOver(dataList, new String[]{"batch"}, orderByList, "rank1", 2); //获取班级排名 DataProcessUtil.rankOver(dataList, new String[]{"batch", "banji"}, orderByList, "rank2", 2); log("语文单科成绩排名情况如下:"); Map<String, List<Student>> groupMap = DataProcessUtil.group(dataList, null, new String[]{"batch"}); for (Map.Entry<String, List<Student>> entry : groupMap.entrySet()) { log("考试批次:" + entry.getKey()); for (Student s : entry.getValue()) { log(String.format("班级:%s 学生:%s 语文成绩:%s 班级排名:%s 全校排名:%s", s.getBanji(), s.getName(), s.getYuwen(), s.getRank2(), s.getRank1())); } log(""); }###結果如下:#########語言單科成績排名情況如下:###考試批次:202302###班級:三年一班學生:張小明語文成績: 130.0 班級排名:2 全校排名:3###班級:三年一班學生:王二小語文成績:128.0 班級排名:3 全校排名:6###班級:三年一班學生:謝春花語文成績:136.0 班級排名:1 全校排名:1###班級:三年二班學生:馮世傑語文成績:129.0 班級排名:3 全校排名:5###班級:三年二班學生:馬功成語文成績:130.0班級排名:2 全校排名:3###班級:三年二班學生:魏翩翩語成績:136.0 班級排名:1 全校排名:1#########可以看到全校排名中有兩個並列第一名兩個並列第三名,且空出了並列所佔用的名次2 和名次4###
以上是Java怎麼模擬rank/over函數實現取得分組排名的詳細內容。更多資訊請關注PHP中文網其他相關文章!