select sa.sp_location_fb
, sp.sp_content
, min(sp.sp_priority) over (partition by sa.sp_location_fb) as min_prior
, sp.sp_priority
from selling_point sp, sp_apply sa
where sp.sp_code = sa.sp_code
and sa.pro_code = '2016030700001'
and sp.sp_priority = min_prior
분명히 min(sp.sp_priority) over (partition by sa.sp_location_fb) as min_prior 여기서 as min_prior 해줫는데
and sp.sp_priority = min_prior 마지막줄에서 에러가 나네요 왜그런거죠...
select절의 실행순서는 아래와 같습니다.
위의 쿼리는 where절을 수행할 시, select절의 알리아스를 사용했으므로 오류가 날수밖에 없습니다.
왜? where절 수행시에는 select절을 읽기 전이기 때문
1. from
2. where
3. group by
4. having
5. select
6. order by
select * from ( select sa.sp_location_fb , sp.sp_content , min(sp.sp_priority) over (partition by sa.sp_location_fb) as min_prior , sp.sp_priority from selling_point sp, sp_apply sa where sp.sp_code = sa.sp_code and sa.pro_code = '2016030700001') where sp.sp_priority = min_prior
Alias 를 바로 인식할 수는 없습니다.
인라인뷰로 묶은 뒤 다음 단계에서 인식 가능합니다.
SELECT * FROM (SELECT sa.sp_location_fb , sp.sp_content , sp.sp_priority , MIN(sp.sp_priority) OVER(PARTITION BY sa.sp_location_fb) min_prior FROM selling_point sp , sp_apply sa WHERE sp.sp_code = sa.sp_code AND sa.pro_code = '2016030700001' ) WHERE sp_priority = min_prior ;
그런데 위 방식은 비효율이 존재합니다.
TOP n 쿼리 방식으로 개선 가능합니다.
MIN 보다는 순위함수인 Rank 함수를 사용하는게 좋습니다.
SELECT * FROM (SELECT sa.sp_location_fb , sp.sp_content , sp.sp_priority , RANK() OVER(PARTITION BY sa.sp_location_fb ORDER BY sp.sp_priority) rk FROM selling_point sp , sp_apply sa WHERE sp.sp_code = sa.sp_code AND sa.pro_code = '2016030700001' ) WHERE rk = 1 ;
만약 sp_location_fb 별 sp_priority 값이 중복되지 않는다면?
RANK 대신 ROW_NUMBER 을 사용해도 되며
이 경우 GROUP BY KEEP 을 이용하는 방법도 가능합니다.
SELECT sa.sp_location_fb , MIN(sp.sp_content) KEEP(DENSE_RANK FIRST ORDER BY sp.sp_priority) sp_content , MIN(sp.sp_priority) sp_priority FROM selling_point sp , sp_apply sa WHERE sp.sp_code = sa.sp_code AND sa.pro_code = '2016030700001' GROUP BY sa.sp_location_fb ;