RANK 쿼리를 만들어 봤습니다.
함수로 만들어진 쿼리는 찾아보니 이미 오래전에 있더군요..
http://database.sarang.net/?inc=read&aid=5007&criteria=pgsql&subcrit=qna&id=5059&limit=20&keyword=&page=82
쿼리문을 보셔서 아시겠지만, 방식은
grp 별로 필요한 순위컬럼을 sort 하여 PK 를 배열로 만들고
필요한 순위만큼 집어내어 실제 테이블과 PK 조인하는 방식입니다.
이 방식도 그렇고.. 아래의 쿼리 방식도 그렇고..
실무에서 얼마나 효율을 낼지 궁금해서
실력 분들의 조언을 구하고저 이렇게 올립니다.
seq 컬럼은 반드시 존재해야 하며 unique 해야 합니다.
아래의 쿼리는 grp 별로 cnt 가 높은 순위 입니다.
create aggregate agg_addrow (
sfunc = array_append,
basetype = anyelement,
stype = anyarray,
initcond = '{}'
);
select * from tab;
seq | grp | other | cnt
-----+-----+-------+-----
1 | 1 | 44 | 1
2 | 1 | 3 | 1
3 | 1 | 5 | 4
4 | 1 | 7 | 2
5 | 2 | 2 | 1
6 | 2 | 8 | 4
7 | 2 | 15 | 2
8 | 2 | 9 | 3
9 | 3 | 1 | 3
10 | 3 | 6 | 2
(10 rows)
select tab .*, rank from tab,
(select _arr[1:4], rank
from (
select agg_addrow(seq) as _arr
from (
select grp, seq from tab order by cnt desc
) _t
group by grp
) _t cross join generate_series(1,4) rank
where rank <= 4
) _t
where tab.seq = any(_t._arr)
and rank = idx(_t._arr, tab.seq)
order by grp, rank;
seq | grp | other | cnt | rank
-----+-----+-------+-----+------
3 | 1 | 5 | 4 | 1
4 | 1 | 7 | 2 | 2
2 | 1 | 3 | 1 | 3
1 | 1 | 44 | 1 | 4
6 | 2 | 8 | 4 | 1
8 | 2 | 9 | 3 | 2
7 | 2 | 15 | 2 | 3
5 | 2 | 2 | 1 | 4
9 | 3 | 1 | 3 | 1
10 | 3 | 6 | 2 | 2
(10 rows)
|