SQL

SQL - IN, EXITS, ANY, ALL

황민준 2022. 12. 10. 16:05

*IN

‘=’비교만 가능하고, OR 조건 검색 결과를 가져온다.

서브쿼리가 먼저 실행되고 그 결과를 바탕으로 메인쿼리가 실행된다.

 

*EXISTS

메인쿼리의 비교 조건이 서브쿼리의 결과 중에 만족하는 값이 있다면 1, 없다면 0

메인쿼리를 먼저 실행한다 -> 메인쿼리로 범위를 좁히고 서브쿼리로 값을 찾는다.

공통된 컬럼이 없는 경우 exists하면 10에 따라 값을 다 보여주거나 다 보여주지 않는다.

등가조인을 사용할 경우(공통된 컬럼이 있을 경우)에는 exists 비교를 통해 조건에 맞는 데이터면 1이어서 보여주고, 조건을 만족하지 않으면 0이기 때문에 보여주지 않는다.

existsin보다 성능이 더 좋다 -> 메인쿼리로 범위를 좁혀놓고 시작하기 때문에

 

*ANY

메인쿼리와 비교조건이 서브쿼리 결과 중 하나라도 일치하면 참이다.

1) = any : in과 같은 효과

2) > any : 최솟값보다 더 크면

3) < any : 최댓값보다 더 작으면

 

*ALL

ANY와 반대 개념

1) = all : any와 같지만 or이 아니라 and 연산이다. -> 값이 하나인 것과 값이 여러 개 인 것을 비교하는 것 자체가 잘못되었으므로 무조건 값이 하나가 나오는 쿼리여야 한다.

2) < all : 최솟값보다 더 작으면

3) > all : 최댓값보다 더 크면

 

=> ANYALLMAX, MIN과 성능 차이가 없기 때문에 아무거나 사용해도 된다.

 

-- 1. IN : = 비교만 가능, OR 조건 검색 결과 내용을 가져온다.
-- 서브쿼리가 먼저 실행되고, 그 결과를 바탕으로 메인쿼리가 동작한다.
select ename, job from emp where deptno in (2,4);
select ename, job from emp where deptno in (select deptno from dept where loc in ('la','boston'));

-- 2. EXISTS : 메인 쿼리의 비교 조건이 서브쿼리의 결과 중에 만족하는 값이 하나라도 존재하면 1 혹은 0 반환
-- 메인쿼리로 범위를 좁히고 서브쿼리로 값을 찾는다.
-- exists는 결과값이 있으면 1, 없으면 0을 반환
select exists (select deptno from dept where loc in ('la','boston')) as bool;

select ename, job, deptno from emp where exists (select deptno from dept where loc in ('la','boston'));
select ename, job, deptno from emp where 1;

select ename, job, deptno from emp where exists (select deptno from dept where loc in ('korea'));
select ename, job, deptno from emp where 0;

-- 그럼 어떻게 사용하는가?
-- 1) 메인쿼리가 실행된다.
select ename, job, deptno from emp;
-- 2) 이 메인쿼리 내용을 서브쿼리에서 걸러준다. (등가조인처럼 양쪽 테이블에 모두 있는 내용을 가져온다.) -> 0이면 값을 안 보여주기 때문에
select ename, job, deptno from emp e where exists (select deptno from dept d where e.deptno = d.deptno);
-- 결과적으로 왜 이렇게 나오나?
-- 공통되는 컬럼이 있을 경우 행마다의 exists 비교를 통해 보여주고 안 보여주고 하는 것이다. -> emp의 deptno와 dept의 deptno가 같은지 계속 비교를 하기 때문에

-- in 과의 사용법 비교
select ename, job from emp where deptno in (select deptno from dept where loc in ('la','boston'));

select ename, job from emp e where exists(select deptno from dept d where d.deptno = e.deptno and (d.loc in ('la','boston')));
-- exists는 in보다 사용이 복잡하지만 성능이 더 좋다.
-- in은 서브쿼리를 통해 조건을 추출하고 메인쿼리의 내용을 검색한다.
-- exists는 메인쿼리를 통해 데이터를 확정하고 그 안에서 서브쿼리 조건을 걸러낸다.
-- 단, exists는 메인쿼리에서 얼마나 데이터를 좁혀놓고 시작하는지가 관건이다.

-- 3. ANY : 메인쿼리와 비교조건이 서브쿼리 결과 중에 하나라도 일치하면 참이다.
-- 1) = ANY : IN과 같은 효과
select ename, job from emp where deptno in (select deptno from dept where loc in ('la','boston'));

select ename, job from emp where deptno = any (select deptno from dept where loc in ('la','boston'));
 
-- 2) > ANY : 최소값보다 크면
-- 직책이 manager인 직원(입사일이 가장 빠른)의 입사일보다 늦은 직원의 이름과 직책과 입사일
-- 1. 직책이 manager인 입사일이 가장 빠른 직원
select MIN(hiredate) from emp where job = 'manager';
-- 2. 입사일이 2015-08-12 보다 늦은 직원 찾기
select ename, job, hiredate from emp where hiredate > '2015-08-12';

select ename, job, hiredate from emp where hiredate > (select MIN(hiredate) from emp where job = 'manager');

select ename, job, hiredate from emp where hiredate > any (select hiredate from emp where job = 'manager');

-- 3) < ANY : 최대값보다 작으면
-- 직책이 manager인 직원(입사일이 가장 늦은)의 입사일보다 빠른 직원의 이름과 직책과 입사일
select ename, job, hiredate from emp where hiredate < (select MAX(hiredate) from emp where job = 'manager');

select ename, job, hiredate from emp where hiredate < any (select hiredate from emp where job = 'manager');

-- 4. ALL : ANY와 반대 개념
-- 1) = ALL : ANY와 같지만 OR 조건이 아닌 AND 조건이다.
select ename, job from emp where deptno = all(select deptno from dept where loc = 'newyork');

select deptno from dept where loc = 'newyork'; -- 1,3
-- = all 안의 조건은 and 이므로 deptno=1 AND deptno=3 이므로 맞는 조건이 없다.
-- 그래서 결과값이 하나만 나오는 조건으로 사용해야 한다.
select ename, job from emp where deptno = all(select deptno from dept where loc = 'newyork' and deptname = 'sales');

-- 2) > ALL : 최대값보다 크면
select ename, job, hiredate from emp where hiredate > (select MAX(hiredate) from emp where job = 'manager');

select ename, job, hiredate from emp where hiredate > all (select hiredate from emp where job = 'manager');

-- 3) < ALL : 최소값보다 작으면
select ename, job, hiredate from emp where hiredate < (select MIN(hiredate) from emp where job = 'manager');

select ename, job, hiredate from emp where hiredate < all (select hiredate from emp where job = 'manager');