본문 바로가기
DataBase

[MariaDB] 서브쿼리 사용법(단일행 서브 쿼리, 복수행 서브 쿼리) / any, all / ERROR 1242 (21000): Subquery returns more than 1 row 에러

by bkuk 2022. 10. 18.

scott의 급여보다 큰 급여를 받는 사원에 대한 사원이름과 급여를 출력

 

위와 같은 문제가 주어졌을 때

첫번째로는, soctt의 급여를 출력하는 쿼리문을 하나 작성하고,

select sal from emp where ename = "scott";

 

두번째로는,

사원이름과 급여를 출력하는데 where문을 사용해서 첫번째 쿼리문을 조건을 둔다고 생각하면 됩니다.

select ename, sal from emp where sal > (조건)

 

 

따라서, 두 쿼리문을 결합한다면 아래와 같습니다.

select ename, sal from emp where sal > (select sal from emp where ename = "scott");

 

정말 KING만 존재하는지 확인해보겠습니다.

 

사원이름과 급여를 출력하는데 내림차순으로 정렬

명시하지 않을 경우 기본은 오름차순(ASC)입니다.

(ASC 또는 DESC를 입력하지 않은 경우 ASC로 기본적으로 정렬합니다.)

select ename, sal from emp order by sal desc;

 


최고 급여를 받는 사원에 대한 부서번호, 사원이름, 직업, 급여 출력

 

위와 같은 방식으로 max 함수를 통해 최고 급여를 출력해보겠습니다.

select max(sal) from emp;

 

두번째로는, 사원 정보를 출력하는 쿼리문을 작성하겠습니다.

select deptno, ename, job, sal from emp where sal = (최고 급여)

 

두 개의 쿼리문을 결합하면

select deptno, ename, job, sal from emp where sal = (select max(sal) from emp);


 

20번 부서에서 최고 급여를 받는 사원보다 많은 급여를 받는 사원에 대한  부서번호, 사원이름, 직업, 급여 출력

 

 

우선, 20번 부서의 최고 급여를 출력

select max(sal) from emp where deptno = 20;

 

두번째로는, 부서번호, 사원이름, 직업, 급여 출력하는 쿼리문 작성

select deptno, ename, job, sal from emp where sal > (20번 부서의 최고 급여)

 

결합하면

select deptno, ename, job, sal from emp where sal > (select max(sal) from emp where deptno = 20);


 

전체 부서를 대상으로 20번 부서에 근무하는 직책과 같은 사원에 대한 사원번호, 사원이름, 직책을 출력

우선, 20번 부서에 직책을 출력하는데, 두 가지 방법이 있습니다.

 

중복을 고려하지 않은 쿼리문과

select job from emp where deptno = 20

 

중복을 고려한 쿼리문

select distinct job from emp where deptno = 20

 

두번째는, 사원번호, 사원이름, 직책을 출력하는 쿼리문을 작성해서 위 조건을 결합해서 출력해 보겠습니다.

select empno, ename, job from emp where job = ( select job from emp where deptno = 20 );

위 처럼 오류가 발생합니다. 

 

그 이유는 서브쿼리의 내용이 여러 개가 출력되므로, 조건에 쓸 수 없다고 합니다.

따라서 or이라는 연산와 같은 의미를 가진 in을 사용해서 출력해보겠습니다.

select empno, ename, job from emp where job in (select job from emp where deptno = 20);


부서별 최고 급여를 갖는 사원에 대한 정보 출력

 

부서별 최고 급여 출력

select max(sal) from emp group by deptno

 

위 쿼리문을 조건으로 두고 급여 출력

select deptno,empno, ename, sal 
from emp 
where sal in (select max(sal) from emp group by deptno) order by deptno;

 

주의

*아래와 같이 서브 쿼리를 사용하지 않았을 때 max(sal)을 통해서 출력되는 값은 가장 초기에 존재하는 부서번호(dept)의 사원이 출력됨. 쉽게 설명해서 최고급여만 출력되는 것이지, 해당 사원이 최고급여는 아니라는 의미

select deptno, empno, ename, sal, max(sal) from emp
    -> group by deptno;

 

지금까지 앞에서 단일행 서브 쿼리를 어떻게 사용하는지에 대해서 알아봤습니다.

 


지금부터는 복수행 서브 쿼리를 어떻게 사용하는지에 대해서 살펴보겠습니다.

 

 

직책이 "manager"인 사원들급여보다 적은 사원들에 대한 정보 출력해보겠습니다.

select ename, job, sal from emp where sal < (select sal from emp where job ="manager");

 

위와 같이 에러가 발생합니다.

그 이유는 위에서 작성한 서브 쿼리문은 서브쿼리의 결과가 여러 행이기 때문입니다.

이럴때는 in / any, all 과 같이 사용해야합니다.

< any 서브쿼리의 리턴값 중 최대값 보다 작은
> any 서브쿼리의 리턴값 중 최소값 보다 큰
< all 서브쿼리의 리턴값 중 최소값 보다 작은
> all 서브쿼리의 리턴값 중 최대값 보다 큰

 

직책이" manager"인 사원들의 최저 급여보다도 적은 급여를 받고 있는 사원을 출력하는 문제이기 때문에,

< all을 통해 최소 급여 보다 더 작은 값을 출력해야합니다.

select ename, job, sal from emp where sal < all(select sal from emp where job ="manager");


각 부서의 평균 급여보다 적은 사원들에 대한 정보 출력

select avg(sal) from emp group by deptno;

 

위에서 출력된 값은 부서 별 평균 급여를 표현하고 있으므로, 위 값들보다 더 적은 값을 출력하는 문제기 떄문에

< all을 통해 최소 급여 보다 더 작은 값을 출력해야합니다.

select empno, ename, sal from emp where sal < all(select avg(sal) from emp group by deptno);


MILLER보다 늦게 입사한 사원의 사번, 이름, 입사일을 출력

해당 문제는 서브쿼리의 결과가 1행이기 때문에 단일행 서브 쿼리 방식으로 접근합니다.

 

 

MILLER 입사일 출력

select hiredate from emp where ename = "miller";

 

select empno, ename, hiredate 
from emp 
where hiredate > (select hiredate from emp where ename = "miller");