본문 바로가기
클라우드 활용 자바개발자 양성과정/02. 데이터베이스 활용

05. SUBQUERY

by moca7 2024. 7. 19.

 

ㅁ 서브쿼리 종류

 

ㅁ 서브쿼리는 대부분 단일행 서브쿼리가 많이 사용된다. 

 

ㅁ < 서브쿼리 SUBQUERY >

- 하나의 쿼리문 안에 포함되어있는 또다른 쿼리문

- 메인 쿼리를 위해 보조 역할을 수행

- 서브쿼리가 먼저 실행되고 메인쿼리가 실행된다.

 

ㅁ 서브쿼리의 종류

- SELECT절 : 스칼라 서브쿼리

- FROM절: 인라인 뷰

- WHERE절 : 단일행, 다중행, 다중열, 다중행다중열 서브쿼리

 

 

ㅁ 예제 (노옹철 사원과 같은 부서에 속한 사원들 조회)

 

SELECT DEPT_CODE

FROM EMPLOYEE

WHERE EMP_NAME = '노옹철';   //   D9

 

SELECT EMP_NAME

FROM EMPLOYEE

WHERE DEPT_CODE = 'D9'; 

 

- 이 두 과정을 하나의 쿼리로 축약.

 

 

SELECT EMP_NAME
FROM EMPLOYEE
WHERE DEPT_CODE = ( SELECT   DEPT_CODE 
                                           FROM      EMPLOYEE
                                           WHERE   EMP_NAME = '노옹철' );

 

- 서브쿼리가 먼저 수행된다. 

 

 

ㅇ 변형 (DEPARTMENT 테이블의 직급명도 조회)

 

 

(1) 오라클


SELECT EMP_NAME, NVL(DEPT_TITLE, '부서없음')
FROM EMPLOYEE, DEPARTMENT
WHERE SALARY > (SELECT SALARY 
                FROM EMPLOYEE
                WHERE EMP_NAME = '노옹철'
                )
AND DEPT_CODE = DEPT_ID(+) ;

 

- DEPT_CODE가 NULL인 사원들도 포함하고 싶다면 내부조인이 아닌 외부조인을 해야 함.

 

 

(2) ANSI

 

SELECT EMP_NAME, NVL(DEPT_TITLE, '부서없음')
FROM EMPLOYEE

LEFT JOIN DEPARTMENT ON DEPT_CODE = DEPT_ID
WHERE SALARY > (SELECT SALARY 
                FROM EMPLOYEE
                WHERE EMP_NAME = '노옹철' );

 

 

 

ㅁ < 단일행 서브쿼리 SINGLE ROW SUBQUERY >

- 이걸 많이 씀.

- 서브쿼리의 결과값이 오로지 1개인 경우. 한 열, 한 행인 경우.

- 일반 비교연산자 사용 가능(결과값이 1개이기 때문에)

=, !=, ^=, <>, <, <=, >, >=

 

 

ㅁ 보통 서브쿼리로 푸는 문제들은 조인으로 풀 수도 있다.

뭐가 더 효율적인지는 그때 그때 다름.

 

 

ㅁ 예제 (사수가 선동일인 사원의 사번, 이름, 사수사번)

- 이건 조인이 필수가 아닌 이유가, EMPLOYEE 테이블에 있는 컬럼명만 조회하기 때문.

 

(1) SELF JOIN 방식

 

SELECT E1.EMP_ID, E1.EMP_NAME, E1.MANAGER_ID
FROM EMPLOYEE E1, EMPLOYEE E2
WHERE E1.MANAGER_ID = E2.EMP_ID
AND E2.EMP_NAME = '선동일';

 

 

(2) 서브쿼리 방식

 

SELECT EMP_ID, EMP_NAME, MANAGER_ID
FROM EMPLOYEE
WHERE MANAGER_ID = (SELECT EMP_ID
                    FROM EMPLOYEE
                    WHERE EMP_NAME = '선동일');

 

 

ㅁ 예제 (전지연 사원과 같은 부서원의 사원명과 부서명)

- 이건 조인이 필수인 이유가, DEPARTMENT 테이블의 DEPT_TITLE을 조회해서.

 

(1) 오라클 

 

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID
AND DEPT_CODE = (SELECT  DEPT_CODE
                                       FROM  EMPLOYEE
                                    WHERE  EMP_NAME = '전지연')
AND EMP_NAME <> '전지연';

 

 

(2) ANSI 방식

 

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON DEPT_CODE = DEPT_ID
WHERE DEPT_CODE = (SELECT DEPT_CODE
                    FROM EMPLOYEE
                    WHERE EMP_NAME = '전지연')
AND EMP_NAME <> '전지연';

 

 

ㅁ 예제 (부서별 급여합이 가장 큰 부서의 부서코드)

- 먼저 두 개의 쿼리를 차례로 작성해 본다.

 

     SELECT   MAX( SUM(SALARY )  )
        FROM   EMPLOYEE

GROUP BY   DEPT_CODE;     //    17660000

 

     SELECT   DEPT_CODE
         FROM   EMPLOYEE
GROUP BY   DEPT_CODE
     HAVING   SUM(SALARY)  = 17660000;

 

 

- 서브쿼리 적용

 

     SELECT   DEPT_CODE
         FROM   EMPLOYEE
GROUP BY   DEPT_CODE
      HAVING   SUM(SALARY) =   (     SELECT   MAX( SUM(SALARY ) )
                                                               FROM   EMPLOYEE
                                                       GROUP BY   DEPT_CODE);
                    

- MAX(서브쿼리) 이건 안 됨. 집계함수는 쿼리 안에 있어야 함.  

집계함수는 GROUP BY 뒤인 HAVING, SELECT,  ORDER BY 에 온다.

 

 

 

 

 

 

ㅁ < 다중행 서브쿼리 MULTI ROW SUBQUERY >

- 서브쿼리의 결과값이 여러 행인 경우

- 서브쿼리를 가지고 일반 비교연산자와 함께 사용할 수 없다.

- 앞에 비교대상 컬럼이 온다. 다중행이니까.

- IN, ANY/SOME, ALL

 

비교대상 컬럼    IN    (서브쿼리) : 여러개의 결과값 중에서 한개라도 일치하는 값이 있다면 조회 . (= '= ANY')

비교대상 컬럼 > ANY (서브쿼리) : 비교대상 컬럼과 비교연산을 해서, 서브쿼리의 여러개의 결과값들보다 한번이라도 크면 조회.

비교대상 컬럼 < ANY (서브쿼리) : 비교대상 컬럼과 비교연산을 해서, 서브쿼리의  여러개의 결과값들보다 한번이라도 작으면 조회.

비교대상 컬럼 > ALL (서브쿼리) : 비교대상 컬럼과 비교연산을 해서, 서브쿼리의  모든 결과값들보다 큰 경우를 조회.

비교대상 컬럼 < ALL (서브쿼리) : 비교대상 컬럼과 비교연산을 해서, 서브쿼리의  모든 결과값들보다 큰 경우를 조회.

 

 

ㅁ 예제 (유재식 또는 윤은해 사원과 같은 직급인 사원 조회)

- 두 번으로 나눔.

 

SELECT JOB_CODE

FROM EMPLOYEE

WHERE EMP_NAME IN ('유재식', '윤은해');    // J3, J7

 

SELECT *

FROM EMPLOYEE

WHERE JOB_CODE IN ('J3', 'J7');

 

 

- 서브쿼리 적용

 

SELECT   *
   FROM   EMPLOYEE
WHERE   JOB_CODE IN ( SELECT   JOB_CODE
                                               FROM    EMPLOYEE
                                            WHERE    EMP_NAME IN ('유재식', '윤은해')  );

 

SELECT   *
   FROM   EMPLOYEE
WHERE   JOB_CODE = ANY ( SELECT   JOB_CODE
                                                     FROM    EMPLOYEE
                                                  WHERE    EMP_NAME IN ('유재식', '윤은해')  );

 

 

ㅁ 예제 (사수가 D9부서인 사원의 사번, 이름, 사수사번 조회)

 

SELECT EMP_ID, EMP_NAME, MANAGER_ID
FROM EMPLOYEE
WHERE MANAGER_ID IN (SELECT EMP_ID
                    FROM EMPLOYEE
                    WHERE DEPT_CODE = 'D9')
;

 

 

ㅁ 예제 (대리직급이지만 과장 직급 급여들 중 최소급여보다 더 많이 받는 직원의 사번, 이름, 직급, 급여 조회)

- 사원 < 대리 < 과장 < 차장 < 부장

 

SELECT EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, SALARY
FROM EMPLOYEE, JOB
WHERE EMPLOYEE.JOB_CODE = JOB.JOB_CODE
AND JOB_NAME = '대리'
AND SALARY > ANY(SELECT SALARY
                    FROM EMPLOYEE
                    WHERE JOB_NAME = '과장');

 

- 오류는 안나지만 아무것도 결과가 안 나옴. 이유는 서브쿼리에서, EMPLOYEE 테이블에 JOB_NAME이 없기 때문.

- 이걸 두 단계로 나누면, 각각 다 조인이 필요한 쿼리이다.

 

SELECT    EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, SALARY
   FROM    EMPLOYEE, JOB
WHERE    EMPLOYEE.JOB_CODE = JOB.JOB_CODE
     AND     JOB_NAME = '대리'
     AND     SALARY > ANY(SELECT   SALARY
                                                FROM   EMPLOYEE, JOB
                                             WHERE   EMPLOYEE.JOB_CODE = JOB.JOB_CODE
                                                   AND   JOB_NAME = '과장');

 

 

ㅁ 예제 (차장이지만 모든 부장들의 급여보다 더 많이 받는 직원의 사번, 이름, 직급, 급여 조회 )

 

SELECT    EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, SALARY
   FROM    EMPLOYEE, JOB
WHERE    EMPLOYEE.JOB_CODE = JOB.JOB_CODE
     AND     JOB_NAME = '차장'
     AND     SALARY > ALL  (SELECT   SALARY
                                                FROM   EMPLOYEE, JOB
                                             WHERE   EMPLOYEE.JOB_CODE = JOB.JOB_CODE
                                                   AND   JOB_NAME = '부장');

 

 

 

ㅁ < 다중열 서브쿼리 >

- 서브쿼리의 결과값이 한 행이지만, 나열된 컬럼 수가 여러개일 경우 (컬럼 수는 같아야 함!)

- 여러 컬럼과 동시에 비교할 수 있음.

- 일반 비교연산자 사용 가능.

-  다중열 서브쿼리는 단일행 서브쿼리로도 해결 가능함.

 

 

ㅁ 예제 (하이유 사원과 같은 부서, 같은 직급인 사원의 사원명, 부서코드, 직급코드, 입사일)

 

(1) 단일행 서브쿼리 방식

  

SELECT    EMP_NAME, DEPT_CODE, JOB_CODE, HIRE_DATE
   FROM    EMPLOYEE
WHERE    DEPT_CODE = ( SELECT DEPT_CODE
                                              FROM EMPLOYEE
                                              WHERE EMP_NAME = '하이유')   //  D5. 결과값이 하나라는 것은 단일행 서브쿼리인 것이다.
      AND    JOB_CODE = ( SELECT JOB_CODE
                                           FROM EMPLOYEE
                                           WHERE EMP_NAME = '하이유');   //  J5. 결과값이 하나라는 것은 단일행 서브쿼리인 것이다.

 

(2) 단일행 다중열 서브쿼리 방식

 

SELECT    EMP_NAME, DEPT_CODE, JOB_CODE, HIRE_DATE
   FROM    EMPLOYEE
WHERE    ( DEPT_CODE, JOB_CODE ) = ( SELECT   DEPT_CODE, JOB_CODE
                                                                            FROM   EMPLOYEE
                                                                         WHERE   EMP_NAME = '하이유') ;

 

SELECT    EMP_NAME, DEPT_CODE, JOB_CODE, HIRE_DATE
   FROM    EMPLOYEE
WHERE    ( DEPT_CODE, JOB_CODE ) IN ( SELECT   DEPT_CODE, JOB_CODE
                                                                            FROM   EMPLOYEE
                                                                         WHERE   EMP_NAME = '하이유') ;

 

 

ㅁ < 다중행 다중열 서브쿼리 >

- 서브쿼리의 결과값이 여러행 여러열일 경우

- 여러 컬럼과 동시에 비교 가능, 단 일반 비교연산자 사용 불가

 

 

ㅁ 예제 (각 직급별 최소급여를 받는 사원의 사번, 사원명, 직급코드, 급여 조회)

 

SELECT EMP_ID, EMP_NAME, JOB_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY IN (SELECT MIN(SALARY)
                FROM EMPLOYEE
                GROUP BY JOB_CODE);

 

- 이렇게 한 컬럼만 비교하면 안 됨.

다른 그룹의 최소급여랑 이 그룹의 최소급여랑 우연히 같으면 연결되어서 더 나옴.

 

 

SELECT EMP_ID, EMP_NAME, JOB_CODE, SALARY
FROM EMPLOYEE
WHERE (SALARY,JOB_CODE) IN (SELECT MIN(SALARY),JOB_CODE
                FROM EMPLOYEE
                GROUP BY JOB_CODE);

 

 

ㅁ 예제 (각 부서별 최고급여를 받는 사원의 사번, 사원명, 부서코드, 급여 조회)

 

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE (SALARY, DEPT_CODE) IN (SELECT MAX(SALARY),DEPT_CODE
                FROM EMPLOYEE
                GROUP BY DEPT_CODE);

 

- DEPT_CODE가 NULL인 사원들은 안 나옴.

나오게 하고 싶으면 DEPT_CODE 대신 NVL(DEPT_CODE, '없음') 쓰면 됨. 3곳 다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ㅁ <인라인 뷰 INLINE-VIEW >

- FROM절에 작성된 서브쿼리

- 서브쿼리 수행 결과를 마치 하나의 테이블(임시테이블) 처럼 사용 가능

- 주로 TOP-N 분석시 많이 사용됨. TOP-N 분석은 가장 높은 데이터 일부만을 조회(급여별 최상위 몇 명)하겠다.

 

 

ㅁ 예제 (사번, 이름, 보너스포함연봉, 부서코드 조회)(단, 보너스 포함 연봉이 3000만원 이상인 사람만 조회)

 

(1) 일반

 

SELECT EMP_ID, EMP_NAME, (SALARY * (1+NVL(BONUS, 0)))*12 AS "연봉", DEPT_CODE
FROM EMPLOYEE
WHERE (SALARY * (1+NVL(BONUS, 0)))*12 >= 30000000
ORDER BY 3 DESC;

 

- 이렇게 하면 WHERE에 별칭을 못 씀.

 

 

(2) 인라인 뷰

 

SELECT *
FROM (SELECT EMP_ID, EMP_NAME, (SALARY * (1+NVL(BONUS, 0)))*12 AS "연봉", DEPT_CODE
              FROM EMPLOYEE)
WHERE 연봉 >= 30000000
ORDER BY 3 DESC;    

 

 

ㅁ 예제 (전 사원 중 급여가 가장 높은 상위 5명만 조회)

 

SELECT EMP_NAME, SALARY
FROM EMPLOYEE
ORDER BY 2 DESC;

 

- 지금이야 SALARY가 3700000 이상인 사원만 조회하면 상위 5명이지만, 데이터 자체가 나중에 달라질 수도 있다.

- ROWNUM이라는 오라클에서 제공하는 컬럼 사용.

조회된 순서대로 1부터 순번을 부여해준다.

 

 

 

SELECT EMP_NAME, SALARY, ROWNUM
FROM EMPLOYEE
ORDER BY 2 DESC;

 

- 근데 내가 원하는 결과가 안 나옴.

왜냐하면 ORDER BY가 SELECT절보다 실행순서가 뒤기 때문. 

 

 

SELECT EMP_NAME, SALARY, ROWNUM
FROM EMPLOYEE

WHERE ROWNUM <= 5
ORDER BY 2 DESC;

 

- 그래서 상위 5명을 조회하는 것도 원하는 결과가 안 나옴.

 

 

 

- SELECT 절 전에 ORDER BY가 되어야 내가 원하는 결과가 나온다.

 

 

 

 

ㅇ 아래는 오류 발생

 

 

SELECT *, ROWNUM
FROM (SELECT        EMP_NAME, SALARY, ROWNUM
             FROM           EMPLOYEE
             ORDER BY   2 DESC)
WHERE ROWNUM <= 5;      

 

 

- 이렇게 인라인 뷰에 별칭 부여하면 서브쿼리 안의 ROWNUM(ROWNUM)도 볼 수 있다.

 

 

 

 

ㅁ 예제 (가장 최근에 입사한 사원 3명의 사원명, 급여, 입사일 조회)

 

 

 

ㅁ 예제 (각 부서별 평균급여가 높은 3개의 부서들의 부서코드, 평균급여 조회)

 

SELECT *
FROM (SELECT   DEPT_CODE, TRUNC(AVG(SALARY))
                FROM   EMPLOYEE
        GROUP BY   DEPT_CODE
        ORDER BY   2 DESC) 
WHERE ROWNUM <= 3;

 

- 애초에 인라인 뷰에서 가져온 게 2개 칼럼 밖에 없으니 바깥에 *만 써도 됨.

- 인라인 뷰 끝난 다음에 GROUP BY와 HAVING을 또 하는게 아니고, WHERE로 ROWNUM 쓴다.

 

 

 

ㅁ ROWNUM 단점

- 1부터 시작되는 범위만 조회 가능함.

WHERE ROWNUM BETWEEN 1 AND 3은 제대로 됨.

WHERE ROWNUM BETWEEN 2 AND 4는 오류는 안 나지만 정상적인 결과가 안 나옴.

순서 부여와 조건 검사가 동시에 진행되서.

 

 

 

< WINDOW FUNCTION >

- WHERE절에 작성 불가. 

- SELECT절에만 사용 가능.

 

 

(1) ROW_NUMBER() OVER (정렬기준)

- ROWNUM처럼 순번을 부여해주는 함수

 

 

(2) RANK() OVER (정렬기준)

- 순위를 매기는 함수.

- 동일 순위 이후에 등수를 동일한 인원수만큼 건너 뜀.

(공동 1위 두명 이후 그 다음 순위가 3위)

 

 

(3) DENSE_RANK() OVER (정렬기준)

- 순위를 매기는 함수.

- 동일 순위 이후에 등수를 그냥 무조건 1씩 증가시킴.

 

 

 

ㅁ 예제 (급여가 가장 높은 상위 5명 조회)

 

 

 

- 따로 바깥에 ORDER BY 안 써도 윈도우 펑션쓸 때 오더바이 하면 그대로 나옴.

- ROW_NUMBER는 순위 개념은 아니고, 조회되는 순서대로 순번을 부여함.

 

 

 

 

- ROWNUM과 동일하게 상위 몇명만 조회하고 싶다면 인라인 뷰를 써야 함.

- ROWNUM과 다르게 1부터의 범위가 아니어도 정상 조회됨.

 

 

 

ㅁ 예제 (급여가 가장 높은 상위 5명 조회) (공동 순위면 그만큼 건너 뛰게)

 

SELECT *
FROM (SELECT EMP_NAME, SALARY, RANK() OVER(ORDER BY SALARY DESC) "순위"
             FROM EMPLOYEE)
WHERE 순위 <= 5;

 

- WHERE의 "순위" 자리에 "ROWNUM"써도 결과는 같다.

3~5 사이 이렇게 줬을 때만 다름. 

 

 

 

 

 

 

 

 

ㅁ < 상관 서브쿼리 >

- 일반적인 서브쿼리 방식은 서브쿼리의 결과값을 가지고 메인쿼리에서 활용하는 개념.

- 상관 서브쿼리는 반대로 메인쿼리의 값을 가져다가 서브쿼리에서 활용하는 개념.

메인쿼리의 값이 변경되면 서브쿼리의 결과값도 변경됨.

 

 

ㅁ 예제 (본인 직급의 평균급여보다 더 많이 받는 사원 이름, 직급코드, 급여 조회)

 

 


SELECT EMP_NAME, JOB_CODE, SALARY
FROM EMPLOYEE E
WHERE SALARY >ANY (SELECT         AVG(SALARY)
                                         FROM            EMPLOYEE
                                         GROUP BY    JOB_CODE);

 

- 이렇게 하면 안 됨.

직급별로 비교가 되는게 아니고, 우연히 직급별 AVG(SALARY)보다 더 큰게 있으면 그것도 다 잡힘.

 

 

- 메인쿼리의 E.JOB_CODE 값을 서브쿼리에서 활용한다.  그래서 상관 서브쿼리.

- 상관 서브쿼리는 서브쿼리만 드래그해서 실행 불가능 하다. 

- E.JOB_CODE 자리는 메인 쿼리의 매행 스캔시마다 매번 달라짐 (서브쿼리의 결과값도 매번 다름)

[서브쿼리를 매행 스캔하는 건 다른 서브쿼리도 그렇지만, E.JOB_CODE 때문에 서브쿼리 자체가 달라짐]

 

 

 

ㅁ 예제 (보너스가 본인 부서의 평균 보너스보다 더 많이 받는 사원의 사원명, 부서코드, 급여, 보너스 조회)

 

 

 

ㅁ 상관서브쿼리면서 SELECT절에 작성된 서브쿼리 (스칼라 서브쿼리)

- 조인하면 서브쿼리 꼭 안써도 됨.

- 정답은 없음. 회사에선 수행속도가 더 빠른 쿼리를 사용.

(그걸 체감하려면 데이터가 몇만건이어야 함)

= 스칼라 서브쿼리는 단일행 서브쿼리다. 꼭 결과값이 한 행만 나와야 한다.

= 뿐만 아니라 열도 하나만 나와야 한다. FROM절과 WHERE절이 같아도 여러번으로 나눠서 써야 함.

 

 

ㅁ 예제 (전 사원의 사번, 이름, 직급코드, 직급명 조회)

 

(1) 조인

 

SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE
JOIN JOB USING (JOB_CODE);

 

 

(2) 스칼라 서브쿼리

 

SELECT E.EMP_ID, E.EMP_NAME, E.JOB_CODE, (SELECT  JOB_NAME
                                                                                         FROM  JOB
                                                                                       WHERE  JOB_CODE = E.JOB_CODE) "직급명"
FROM EMPLOYEE E;

 

- 많이 씀. 프로젝트 할 때도. 

- 여기서 E.JOB_CODE를 입력값, JOB_NAME을 출력값이라 함.

입력값(메인쿼리값)과 출력값(서브쿼리값)을 내부 캐시라는 공간에 저장해 둠.

서브쿼리 수행 전에 캐시로부터 먼저 찾아보고 거기에 없으면 서브쿼리를 수행하는 개념.

(J2가 부사장이라는걸 알면, 그 다음에는 J2만 보고 서브쿼리를 수행 안하고 캐시에서 바로 값을 반환) [몰라도 됨]

- 그렇다고 서브쿼리가 항상 좋은 것은 아니고 조인을 쓰는게 좋을 때도 있다. 

 

 

 

ㅁ 예제 (전 사원의 사번, 사원명, 부서명)

 

(1) 조인

 

SELECT EMP_ID, EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
JOIN DEPARTMENT ON DEPT_CODE=DEPT_ID;

 

 

(2) 스칼라 서브쿼리 

 

SELECT EMP_ID, EMP_NAME, (SELECT   DEPT_TITLE
                                                         FROM   DEPARTMENT
                                                      WHERE   DEPT_CODE=DEPT_ID)
FROM EMPLOYEE;

 

 

 

ㅁ 예제 (전 사원의 사번, 사원명, 사수명 조회) (단, 사수가 없으면 "없음"으로)

 

(1) 조인

 

SELECT E1.EMP_ID, E1.EMP_NAME, E2.EMP_NAME
FROM EMPLOYEE E1
JOIN EMPLOYEE E2 ON E1.MANAGER_ID = E2.EMP_ID;

 

 

(2) 스칼라 서브쿼리 

 

SELECT E1.EMP_ID, E1.EMP_NAME, NVL((SELECT   EMP_NAME
                                                                            FROM   EMPLOYEE
                                                                         WHERE    EMP_ID = E1.MANAGER_ID), '없음') AS "사수명"
FROM EMPLOYEE E1;

 

 

 

ㅁ 예제 (전 사원의 사번, 사원명, 급여, 본인 부서의 부서원 수, 본인 부서의 평균 급여)

 

 

(2) 스칼라 서브쿼리

 

SELECT EMP_ID, EMP_NAME, SALARY, (SELECT COUNT(DEPT_CODE)
                                                                      FROM EMPLOYEE
                                                                      WHERE E1.DEPT_CODE = DEPT_CODE) AS "본인부서의부서원수"
                                                                   , TRUNC((SELECT AVG(SALARY)
                                                                      FROM EMPLOYEE
                                                                      WHERE E1.DEPT_CODE = DEPT_CODE)) AS "본인부서의평균급여"
FROM EMPLOYEE E1;

 

- 스칼라 서브쿼리는 행 뿐만 아니라 열도 1개여야 한다.

FROM절과 WHERE절이 똑같아도 나눠서 써야 한다.

- WHERE에서 어차피 다 걸러서 GROUP BY DEPT_CODE가 없어도 똑같음.

- 집계함수는 GROUP BY 없이도 쓸 수 있음. 결과는 한 행.