-- 10명 이하만 입사한 년도별 부서이름 , 부서별 입사 사원수 -- 아직 부서에 배치되지 않은 경우도 표시 -- 50번 부서는 제외 select to_Char(E.hire_date , 'yyyy') as hire_date , nvl(D.department_name,'**Undefined**') as department_name , count(E.employee_id) as cnt from employees E , departments D where E.department_id = D.department_id(+) --and E.department_id != 50 -- <<< 1. 여기를 추가하면 department_id가 null인 결과가 사라집니다 group by to_Char(E.hire_date , 'yyyy') , nvl(D.department_name,'**Undefined**') having count(E.employee_id) <= 10 order by department_name;
어디에 나와있는 문제는 아니구요 그냥 만들어본 문제입니다.
위 코드의 1부분을 추가하면 결과에서 department_id가 null인 결과가 사라집니다.
그 이유와 해결 방법을 알고싶습니다.
1. null 을 비교하면 결과는 항상 false 이므로 널에 대한 처리가 필요
- 변경전 : AND e.department_id != 50
- 변경후 : AND NVL(e.department_id, 0) != 50
2. Group by 에서 NVL 사용은
- 그룹바이에서 nvl 을 제거하고 select 절에서만 nvl 해도 결과는 같음
- 그룹바이에서 nvl 하면 전체 사원수 만큼 nvl 처리를 하게 되는데
- 그룹바이에서 nvl 을 제거하면 부서수 만큼만 NVL 하게 됨
- NVL 반복 사용 제거 -> 쿼리가 간결해짐
- NVL 사용 부하 감소
3. COUNT(e.employee_id) 는
- 어차피 employee_id 는 널일 수 없으므로
- COUNT(*) 로 바꾸는게 좋습니다.
- COUNT(컬럼)을 하게 되면 컬럼이 널인지 아닌지 하나하나 체크하게 됩니다.
- COUNT(*) 하면 체크 없이 그냥 카운트 하게 됩니다.
SELECT TO_CHAR(e.hire_date, 'yyyy') AS hire_date , NVL(d.department_name, '**Undefined**') AS department_name , COUNT(*) AS cnt FROM employees e , departments d WHERE e.department_id = d.department_id(+) AND NVL(e.department_id, 0) != 50 GROUP BY TO_CHAR(e.hire_date, 'yyyy') , d.department_name HAVING COUNT(*) <= 10 ORDER BY department_name ;