https://school.programmers.co.kr/learn/courses/30/lessons/276036

 

select (
    CASE 
        WHEN (SKILL_CODE & (select sum(CODE) from SKILLCODES where CATEGORY like 'Front%')) 
            and SKILL_CODE & (select CODE from SKILLCODES where NAME = 'PYTHON') THEN 'A'
        WHEN SKILL_CODE & (select CODE from SKILLCODES where NAME = 'C#') THEN 'B'
        WHEN SKILL_CODE & (select sum(CODE) from SKILLCODES where CATEGORY like 'Front%') THEN 'C'
    END) as GRADE, ID, EMAIL
from DEVELOPERS
  • 이 문제를 풀며 위와 같이 case ~ end 구문을 사용해 A, B, C를 선별해주는 작업을 거쳤다.
  • 이 때 case ~ end 구문에 해당되지 않는 행은 null로서 데이터가 들어가게 되었다.
  • 그렇게 where 절에서 grade is not null 조건을 넣어주고 실행했는데 grade에 대해 알 수 없는 컬럼이라는 에러가 발생했다.
  • 그렇게 고민하며 풀는 동안 스파게티 코드가 되었고 이건 아니다 싶어서 답안을 찾아본 결과 where 절이 아닌 having에서 grade is not null 조건을 걸어 처리하는 것을 보았다.

group by와 having 절에서는 가능한 이유는?

  • GROUP BY와 HAVING은 select 절에서의 별칭을 '결과로 쓰기 위해 준비된 표현식'으로 이해한다.
  • 즉, SQL 엔진은 SELECT 절의 표현식(예: CASE ... AS GRADE)을 실제로 실행하지는 않았어도, 이 표현식의 정의는 이미 알고 있고, 이를 GROUP BY/HAVING 절에 필요한 경우 재사용할 수 있다.
  • -> 별칭만 가져다 쓰는 용도이므로 가능하다.

where 절에서는 안 되는 이유는?

  • 실행 순서 차이
    • WHERE는 원시 데이터를 필터링하는 단계이다.
    • 따라서 아직 SELECT의 표현식 정의를 참조할 수 없다.
    • -> 테이블 고유의 컬럼만을 사용한다.
select (
    CASE 
        WHEN (SKILL_CODE & (select sum(CODE) from SKILLCODES where CATEGORY like 'Front%')) 
            and SKILL_CODE & (select CODE from SKILLCODES where NAME = 'PYTHON') THEN 'A'
        WHEN SKILL_CODE & (select CODE from SKILLCODES where NAME = 'C#') THEN 'B'
        WHEN SKILL_CODE & (select sum(CODE) from SKILLCODES where CATEGORY like 'Front%') THEN 'C'
        ELSE NULL
    END) as GRADE, ID, EMAIL
from DEVELOPERS
group by GRADE, ID, EMAIL
having GRADE is not NULL
order by GRADE, ID
;

https://devmemo-nastorond.tistory.com/59

 

cf) 혹은 CTE를 만들고, where절로 필터링해주면 된다.

+ Recent posts