DB&JDBC(09) - HAVING, IN & NOT IN - 수업 32일차
목차
HAVING 복습
having
에서는 별칭을 사용할 수 없었는데 이 부분을 살펴보고 넘어가겠습니다.
실행 순서의 문제인데, select
에서 별칭을 설정하기 전에 먼저 조건 구문인 having
구문이 실행되기 때문입니다. 쉽게 생각해보면 수학 연산자에서의 우선순위 관계를 생각해보시면 이해가 쉬우실 것 같습니다.
사칙연산에서 괄호 안의 연산이 먼저 이루어지고 곱셈, 나눗셈 그리고 더하기 빼기 순으로 연산을 하듯, sql문은 조건문을 먼저 수행한다고 합니다.
MEMORY AREA 복습
메모리 영역을 복습해보겠습니다. 수업 중 질문이 나온 부분이 map
관련된 질문이었는데, 여기서 꼭 짚고 넘어가야 할 부분이 바로 메모리 영역입니다.
다들 아시다시피 지역변수는 스택에 값이 저장되고, 객체는 힙에 저장됩니다. ArrayList를 사용해서 리스트의 값으로 다시 map을 사용한 예제가 있었는데 이 부분에서 많은 분들이 질문을 주셔서 저도 쉽게 놓쳤던 부분들을 다시금 생각해 볼 수 있었습니다.
9번 라인을 보시면 map1
참조변수에 새로운 HashMap
객체를 생성해서 연결해줍니다.
그리고 10, 11번 라인에서 name
(key)에 짬뽕
, price
(value)에 7000원
을 입력해준 뒤 12번 라인에서 list1
에 map1
의 주소를 연결해줍니다.
위의 그림에서는 14번 라인까지의 입력 결과이고, list1에 연결된 객체의 name
을 출력해보면 짜장면
이 나오게 됩니다.
그리고 16, 17번 라인에서 다시 map1
의 name
과 price
키에 새로운 데이터를 입력해주고 18번 라인에서 입력한 map1
데이터를 list1
에 추가해서 출력을 해보면 값이 어떻게 나오는지 확인해보겠습니다.
그림과 같이 입력되며 20번 라인에서 값을 출력해보면 짬뽕
이 나오게 됩니다.
리스트에는 총 2개의 값이 있지만 둘 모두 같은 주소를 가르키고 있고, 연결된 객체의 데이터는 처음의 짜장면
, 5000원
에서 짬뽕
, 7000원
으로 값이 새롭게 할당되었기 때문에 22~25번 라인에서 for loop로 리스트 안의 값들을 모두 출력시켜보더라도 2번의 결과 모두 짬뽕
7000
원이 나오게 됩니다.
이제 코드를 약간 수정해보겠습니다.
입력하는 데이터와 순서는 비슷합니다.
다만 이번에는 17, 18번 라인에서 name
과 price
값을 할당하기 전에 새로운 HashMap
객체를 생성해서 map2
참조변수와 연결하고 name
과 price
값을 할당합니다.
그 뒤에는 똑같이 list1
에 값을 추가하여 출력된 결과를 예상해보고 확인합니다.
구조를 보면 그림과 같습니다.
첫번째와는 달리 map2
를 새로운 객체와 연결시켜줬기 때문에 데이터를 덮어 씌우는 것이 아니라 2개의 서로 다른 HashMap
객체에 key
,value
가 입력되고, list
에 이 객체들이 연결되게 됩니다.
그래서 22번 라인의 출력 결과를 확인해보면 전과 달리 짜장면
5000원
과 짬뽕
7000원
이 한 번씩 출력됩니다.
만약 9번, 16번 라인에서 모두 같은 이름의 map1
참조변수에 새로운 객체를 연결시키려고 했다면 두번째 연결에서 컴파일 에러가 발생할 겁니다.
참조변수는 한 번에 두 개의 객체를 가리킬 수 없기 때문인데, 컴파일러 입장에서 본다면 둘 중 어떤 주소를 골라야 할지 모르기 때문에 에러가 발생하게 됩니다.
IN, NOT IN
IN과 NOT IN 연산자에 배워보도록 하겠습니다.
IN 연산자
: 특정값이 포함되는 데이터를 조회하고자 할 때 사용하는 연산자입니다.
1
2
3
select 컬럼, 컬럼
from 테이블명
where 컬럼 in('또래오래', '대한곱창')
NOT IN 연산자
: 특정값이 포함되지 않는 데이터를 조회하고자 할 때 사용하는 연산자입니다.
1
2
3
select 컬럼, 컬럼
from 테이블명
where 컬럼 not in('또래오래', '대한곱창')
IN과 NOT IN은 and
와 or
를 사용해서도 표현할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- maker가 대한곱창, 이춘복참치 인 food 정보를 조회
select id,name,maker,price
from FOOD
where maker in('대한곱창','이춘복참치');
-- 위 sql을 아래와 같이 표현할 수 있다
select id,name,maker,price
from FOOD
where maker='대한곱창' or maker='이춘복참치';
-- not in
select id,name,maker,price
from FOOD
where maker not in('대한곱창','이춘복참치');
-- 위 sql을 아래와 같이 표현할 수 있다
select id,name,maker,price
from FOOD
where maker<>'대한곱창' and maker<>'이춘복참치';
예제
마지막으로 두 개의 예제를 살펴보도록 하겠습니다.
- 전체 음식의 평균가보다 maker별 음식 평균가가 낮은 maker의 음식정보(name,price,maker) 를 조회하는 예제입니다.
1
2
3
4
5
6
7
8
9
select name,price,maker
from food
where maker in(
select maker
from food
group by maker
having avg(price)<(select avg(price) from food)
)
order by price desc;
- s_employee 테이블에 저장된 전체 사원 정보의 평균월급(salary)보다 직종별(job) 평균월급이 낮은 직종(job)에 해당하는 사원 정보를 조회(salary 내림차순 정렬)하는 메서드입니다.
1
2
3
4
5
select empno,name,job,salary from s_employee
where job in(
select job from s_employee
group by job having avg(salary)<(select avg(salary) from s_employee)
) order by salary desc
댓글남기기