안녕하세요. row_number 쿼리 문의 드립니다.
rn이 1인 데이터를 가져오려면 아래의 쿼리를 감싼후에 where rn = 1로 가져올 수가 있는데
현재의 쿼리에서 rn이 1인것만 가져올 수 있는 방법이 있을까요??
SELECT a1.member_no , row_number() OVER (PARTITION BY a1.member_no ORDER BY a1.avg_hit_rate desc , a1.top_hit_cnt ) as rn , a1.join_no FROM ht_typing_contents_join_log a1 WHERE a1.reg_date >= STR_TO_DATE(CONCAT( date_format(now(), '%Y%m%d' ) , '000000'), '%Y%m%d%H%i%s') AND a1.reg_date <= STR_TO_DATE(CONCAT( date_format(now(), '%Y%m%d' ) , '235959'), '%Y%m%d%H%i%s') and a1.success_yn = 'Y' AND a1.len_type = '1'
SELECT a1.member_no , row_number() OVER (PARTITION BY a1.member_no ORDER BY a1.avg_hit_rate desc , a1.top_hit_cnt ) as rn , a1.join_no from ht_typing_contents_join_log a1 where a1.reg_date >= STR_TO_DATE(CONCAT( date_format(now(), '%Y%m%d' ) , '000000'), '%Y%m%d%H%i%s') and a1.reg_date <= STR_TO_DATE(CONCAT( date_format(now(), '%Y%m%d' ) , '235959'), '%Y%m%d%H%i%s') and a1.success_yn = 'Y' and a1.len_type = '1' and a1.[pk] = (select distinct first_value([pk]) over(partition by member_no order by avg_hit_rate desc, top_hit_cnt) from ht_typing_contents_join_log t where member_no = a1.member_no)
정렬 후 1건을 가져오는 쿼리에서
1건을 가져오기 위해서는 전체를 읽어야 합니다.
인덱스를 이용해 1건을 읽는 방법도 있긴 한데, 이는 그룹별 1건이 아닌 전체 1건의 경우에 해당합니다.
또한, 정렬기준이 비율, 건수 이런 종류인걸로 봐서 인덱스가 있을 것 같지는 않네요.
만약 있다고 하더라도 정렬이 DESC 와 ASC 가 섞여 있어 이용하기 어렵습니다.
이런 류의 쿼리(Top N 쿼리)에서는 ROW_NUMBER 가 그나마 효율적인 쿼리입니다.
전체를 읽고 정렬을 수행하기는 하지만 정렬용 공간을 적게 사용합니다.
정렬용 공간을 전체 행수가 아닌 맴버수 만큼만 사용하게 됩니다.