Oracle DBA/SQL

077 서브 쿼리 사용하기 7(SELECT절의 서브 쿼리)

Nuez 2023. 7. 5. 15:31
반응형
서브쿼리 사용 가능 서브쿼리 이름
SELECT O Scalar Subquery
FROM O In line view
WHERE O Subquery
GROUP BY X X
HAVING O Scalar Subquery
ORDER BY O Scalar Subquery

 


문제 418. 토탈월급을 출력하시오.

SELECT SUM(sal)
FROM emp;


문제 419. 이름, 월급, 토탈월급을 출력하시오. 

SELECT ename, sal, SUM(sal) OVER()
FROM emp;


문제 420. 이름, 월급, 토탈 월급을 출력하는데, SELECT절의 서브쿼리인 스칼라 서브쿼리를 이용해서 출력하시오.

SELECT ename, sal, (SELECT SUM(sal) FROM emp) AS 토탈월급
FROM emp;

* SELECT절의 서브쿼리인 스칼라 서브쿼리는 emp 테이블의 건수만큼 반복되면서 수행됨.(WHERE절 안썼을 경우)

cf. WHERE절 쓸 경우 WHERE절에 의해 걸러진 행 갯수만큼 반복 수행.

 

=> 가져오는 테이블의 건수만큼 서브쿼리가 수행되므로 속도가 느려짐. 악성SQL. 튜닝의 필요성


문제 421. 직업이 SALESMAN인 사원들의 토탈월급을 출력하시오.

SELECT SUM(sal)
FROM emp
where job = 'SALESMAN';


문제 422. 이름, 월급, 직업이 SALESMAN인 사원들의 토탈월급을 출력하시오.

전체 직원 이름, 월급 옆에 세일즈맨 월급 총합 쭉 출력하면 됨. (본인 직업이 뭐든간)

SELECT ename, sal, (SELECT SUM(sal) FROM emp WHERE job = 'SALESMAN') AS s_tot
FROM emp;


문제 423. 이름, 월급, 직업이 SALESAMAN인 사원들의 토탈월급, 직업이 SALESAMAN인 사원들의 최대월급, 직업이 SALESAMAN인 사원들의 최소월급을 출력하시오.

SELECT ename, sal, 
        (SELECT SUM(sal) FROM emp WHERE JOB = 'SALESMAN') 토탈월급,
        (SELECT MAX(sal) FROM emp WHERE JOB = 'SALESMAN') 최대월급,
        (SELECT MIN(sal) FROM emp WHERE JOB = 'SALESMAN') 최소월급
FROM emp;

 

위의 SQL의 문제점은 emp 테이블의 건수만큼 스칼라 서브쿼리의 select문이 반복된다는 것.

(emp 테이블을 각각 3번 액세스)


흔히 잘못 접근하는 예 

1. 일단 총합, 최댓값, 최솟값을 한 번에 출력하는 쿼리를 작성한다. 

SELECT SUM(sal), MAX(sal), MIN(sal)
FROM emp
WHERE JOB = 'SALESMAN';

이렇게 하면 한번에 세가지 값이 나옴. 


2. 위의 쿼리를 메인쿼리의 SELECT절에 스칼라 서브쿼리로 한번에 넣음. 

SELECT ename, sal, 
	(SELECT SUM(sal), MAX(sal), MIN(sal) -- 1단계에서 작성한 부분
		FROM emp
		WHERE job = 'SALESMAN')
FROM emp;

오류 메세지 출력

ORA-00913: 값의 수가 너무 많습니다

00913. 00000 -  "too many values"


스칼라 서브쿼리의 특징

: 하나의 값만 출력할 수 있음.

 

한번에 총합, 최대, 최솟값을 다 출력하려고 하기 때문에 오류 발생.

즉 423번 맨 처음처럼 스칼라 서브쿼리를 하나씩 작성해 콤마(,)로 연결해야함. 


문제 426. 이름, 월급, 부서위치를 출력하시오.

 

EQUI JOIN 방식 

SELECT E.ename, E.sal, D.loc
FROM emp E, dept D
WHERE E.deptno = D.deptno;

Scalar Subquery 방식

SELECT ename, sal, (SELECT loc FROM dept D WHERE E.deptno = D.deptno) AS 부서위치
FROM emp E;


문제 427. 부서번호, 이름, 월급, 자기가 속한 부서번호의 평균월급을 출력하시오. 

(scalar subquery로)

SELECT empno, ename, sal, 
	(SELECT AVG(sal) 
    	FROM emp S
    	WHERE S.deptno = E.deptno) 부서평균
FROM emp E;


수행순서


1. 메인쿼리 FROM
2. 메인쿼리 SELECT
3. 2의 행 하나하나마다 서브쿼리 WHERE
4. 2의 행 하나하나마다 서브쿼리 SELECT