[JAVA] 랭킹 구하기

yeonjoo913·2023년 11월 16일

JAVA

목록 보기
15/19

목록의 순위를 구해야했는데, JAVA에서 처리하는 법과 Query로 처리하는 법 둘 다 정리해보고자 한다.

조건

중복 순위 개수만큼 다음 순위 값을 증가 시켜라

JAVA에서 처리

  • 시간복잡도 O(n)으로 처리
    for문 중첩으로 하면 시간복잡도 O(n^2)이지만, 점수별로 몇등에 해당하는지 구하면 시간복잡도는 O(n)이 된다.
public class Test {

    private static List<Integer> rankOfScore = new ArrayList<>(Arrays.asList(new Integer[101]));
    private static List<Integer> input = Arrays.asList(77, 79, 82, 100, 66, 77);

    static {
        for (int score = 0; score <= 100; score++) {
			// 이 점수보다 높은 점수에 몇명이 있는지만 판별
            long rank = input.stream()
                    .filter(s -> s > score)
                    .count();
            rankOfScore.set(score, (int) rank + 1);
        }
    }

    public static String solution(List<Integer> scores) {
        List<Integer> result = scores.stream()
                .map(score -> rankOfScore.get(score))
                .collect(Collectors.toList());

        return result.toString();
    }

		public static void main(String[] args) {
        System.out.println(solution(input));
    }
}
  • 위로 로직을 참고하여 Map으로 처리
    salesQy를 음수값으로 처리되야하는 부분이 있어 위의 로직을 사용하면 에러가 난다. 그래서 map으로 처리하였다.
private List<BrandPrdtSalesDto> setPrdtRanking(List<BrandPrdtSalesDto> targetList) {
        // 판매량 작은것부터 정렬
        List<Integer> rankOfScore = targetList.stream()
                .sorted(Comparator.comparing(BrandPrdtSalesDto::getSalesQy))
                .map(i -> i.getSalesQy())
							  .collect(Collectors.toList());

        // (index,saleQy) 형태로 사용
        Map<Integer,Integer> scoreMap = IntStream.range(0,rankOfScore.size())
                .boxed()
                .collect(Collectors.toMap(i -> i,rankOfScore::get));

        Map<Integer,Integer> resultMap = new HashMap<>();

        // 랭킹구하기
        scoreMap.entrySet().stream()
                .forEach(index -> {
                    Integer salesQy = index.getValue();
                    long rank = targetList.stream()
                            .filter(s -> s.getSalesQy() > salesQy)
                            .count();
                    resultMap.put(salesQy,(int) rank + 1); //(salesQy,ranking)
                });
        //랭킹 세팅
        ...

        return targetList;
    }

Query에서 처리

  • RANK() 함수 사용
    순위함수는 OVER 절과 함께 사용해야 하며 OVER절 내부의 ORDER BY 절에 순위 칼럼을 지정하면 된다.
    동일한 값일 경우, 동일한 순위를 부여한다.
    앞에 동일한 순위가 부여되어있을 경우, 해당 순번만큼 건너뛰고 순번을 부여한다.
select b.BRAND,
	   b.MONTHLY_SALES_QY,
       RANK() over (ORDER BY b.MONTHLY_SALES_QY desc ) as rank_salesQy
from STATS_BRAND_SALE b
where b.KEYWORD_ID = 6  and b.BRAND != ''
group by b.BRAND
order by b.MONTHLY_SALES_QY desc ;
brandmontly_sales_qyrank
필립스461
오랄비461
위니아343
샤오미314
  • DENSE_RANK() 함수 사용 (번외)
    동일한 순위가 있어도 순차적인 순위를 부여하고 싶을 때 사용하면 된다.
    앞에 동일한 순위가 부여되었어도 순차적으로 순번을 부여한다.
select b.BRAND,
	   b.MONTHLY_SALES_QY,
       DENSE_RANK() over (ORDER BY b.MONTHLY_SALES_QY desc ) as rank_salesQy
from STATS_BRAND_SALE b
where b.KEYWORD_ID = 6  and b.BRAND != ''
group by b.BRAND
order by b.MONTHLY_SALES_QY desc ;
brandmontly_sales_qyrank
필립스461
오랄비461
위니아342
샤오미313

참고 블로그

https://way-be-developer.tistory.com/201

profile
주니어 백엔드 개발자. 까먹는다 기록하자!

0개의 댓글