서브쿼리

 

다른 하나의 SQL문장안에 기술된 SELECT문장을 말한다.(SELECT문 안의 SELECT문)

조건을 먼저 살펴보면

-서브쿼리는 괄호로 묶어야 함 

-서브쿼리만을 단독 실행 시 실행이 가능해야 한다

-두 종류의 연산자가 서브쿼리에 사용된다. 

 =  ,  >  ,   >=  ,  <  ,  <=  ,  <>  ,  !=  (단일행 연산자)  =>  레코드 결과 값이 1개나옴

 혹은 IN, NOT IN(복수행 연산자)등    => 결과값이 여러 개 나옴

- 서브쿼리는 연산자의 오른쪽에 기술 되어야 한다

-단일행 서브 쿼리에는 단일행 연산자를 다중행 서브쿼리에는 복수행 연산자를 사용한다

-서브쿼리는  SELECT절,FROM절 WHERE절등에 위치할 수 있다.  웬만한 절에는 어디서나 다 사용 가능

 

역시 설명보단 실전이지!!!

1. 최소연봉을 이 얼마인지 알기 위한 코드

SELECT MIN(SAL) FROM EMP;

2. ++ 나는 최소연봉 받는 사람의 이름이나 그런 정보를 알고 싶다!!! 

 

연습연습연습!!

문제)부서별 최고연봉으르 받는 사람들의 이름 직무를 출력하라

1. 먼저  부서별 최고연봉을 구하는 로직을 작성해 놓고!  (그룹함수 잘 사용해야 함!)

SELECT  DEPTNO  MAX(SAL)  FROM EMP GROUP BY DEPTNO     ==> 값이 단일값이 아닌 표로 나온다!!

 

2 .틀을 만들어 놓아

SELECT ENAME, JOB  FROM EMP 

WHERE   여기에 어떤 조건을 해야 하는지 의문스럽군...

 

3. 1번과 2번 둘을 조합해!!

SELECT ENAME, JOB  FROM EMP

WHERE  ( DEPTNO,SAL  IN (SELECT  DEPTNO  MAX(SAL)  FROM EMP GROUP BY DEPTNO   ) ;

  ==WHERE절을 풀어서 보면

WHERE DEPTNO = 30 AND SAL = 2850 OR DEPTNO = 20 AND SAL=3000 OR DEPTNO =10 AND SAL =5000;
WHERE (DEPTNO,SAL)IN ((30,2850),(20,3000),(10,5000));  이런 해설임!!

 

 

문제2)  최소연봉/최대연봉을 받는 사람의 이름과 연봉,직무를 출력하라, 연봉이 낮은 사람이 먼저 출력..

1. 최소연봉 받는 사람의 정보 구하기

SELECT ENAME, SAL , JOB FROM EMP

WHERE SAL = (SELECT MIN(SAL) FROM EMP );

2. 최대연봉 받는 사람의 정보 구하기

SELECT ENAME,SAL,JOB FROM EMP

WHERE SAL = (SELECT MAX(SAL) FORM EMP);

3. 둘을 합쳐!

SELECT ENAME,SAL,JOB FROM EMP

WHERE SAL IN((SELECT MIN(SAL) FROM EMP ),(SELECT MAX(SAL) FORM EMP))

ORDER BY SAL;

 

문제3-1) 부서배치가 안된 직원 구하기

걍 부서가 없는직원 구하는거.. 

SELECT LAST_NAME ||' '|| FIRST_NAME, SALARY,HIRE_DATE

FROM EMPLOYEES

WHERE DEPARTMENT_ID IS NULL;

문제 3-2) 인원충원이 안된 모든 부서의 코서코드명 출력

====>이거 서브쿼리로 바꾸기

1. 대략적인 감을 찾기위해 하드코딩 

SELECT DNAME

FROM DEPT

WHERE DEPTNO NOT IN(10,20,30);

2. 참고해서 코딩

SELECT DNAME

FROM DEPT

WHERE DEPTNO NOT IN(SELECT DISTINCT DEPTNO FROM EMP

  => 어떤개념??? EMP 사람들 정보가 있는 테이블에서 DEPTNO 부서코드 가 부여된 것들을 다 빼면 NULL값만 남겠지

그게 인원이 없는 부서!! 와우( DISTINCT 부서는 중복이 가능하니까 간편하게 하려고 중복제거한거)

 

문제4-1) 연봉이 평균 이하인 직원들의 정보 출력

SELECT ENAME, SAL,DEPTNO,HIREDATE

FROM EMP

WHERE SAL <= (SELECT AVG(SAL) FROM EMP);

문제4-2) 부서별 최고연봉을 받는 사람들의 이름과 직책 , 입사일 정보 출력

SELECT ENAME,SAL,DEPTNO,HIREDATE

FROM EMP

WHERE (SAL,DEPTNO) IN ( SELECT MAX(SAL), DEPTNO FROM EMP GROUP BY DEPTNO )

                                                               =>부서별이니 부서랑 연봉정보 필요하고 그룹함수가 쓰였으니 같이  나머지도 같이 그룹화 해줘야지 에러가 안나겠지?!

문제 4-3) 4-2번에서 부서명도 같이 출력

SELECT ENAME,SAL,DEPTNO,HIREDATE, DNAME   =>부서명은 DEPT 테이블에 있으니까 JOIN!!

FROM EMP E JOIN DEPT D ON D.DEPTNO = E.DEPTNO

WHERE (SAL,DEPTNO) IN ( SELECT MAX(SAL), DEPTNO FROM EMP GROUP BY DEPTNO )  

 

TOP 쿼리/구간쿼리

랭킹함수같은 느낌? 얻어진 결과를 위에서 순서대로 몇 개만 가져오려고 할 때 쓰는 것

하기전에 알아야 할 명령어  ROWNUM 이건 데이터가 입력된 순서 혹은 서브쿼리에 의해 생성된 테이블에 레코드가 생성된 순서대로 내부적으로 번호가 부여되는데 그 번호를 저장한 컬림 이름임! 이건 내갸 만든게 아니고 오라클 내부에서 원래 있던 컬럼임TOP 쿼리 구조는 그냥 외우는게 마음 편함! TOP쿼리에서 파생된게 구간쿼리인데 개인적으로 구간쿼리 형식 하나 외워놓는게 더 편한 것 같다.

 

우선 탑쿼리 (연봉이 높은순으로 위에서 3명)

SELECT T.*    ->모든걸 꺼내온다고는 하지만 이미 서브쿼리에서 ENAME , SAL 밖에 지정되어있지않아서 두 개만 출력 됨FROM  (SELECT ENAME,SAL FROM EMP ORDER BY SAL DESC) T    ->서브쿼리 자체를 별칭 함!WHERE ROWNUM <= 3 ;

 

구간쿼리

SELECT *
FROM (SELECT T.*,  ROWNUM RN FROM

(SELECT * FROM EMP ORDER BY SAL)T )  => 서브쿼리로 원하는 순서로 나열해 놓고
WHERE RN BETWEEN 5 AND 8;         => 원하는 구간을 가져 옴. 연봉이 5~8 구간 사이인 사람 

 

쪼개서 보여드리리

 

SELECT T.* , ROWNUM     
FROM (SELECT * FROM EMP ORDER BY hiredate DESC)T;   => 연봉기준으로 나열한거 요게 밑에 있는 쿼리안으로 들어간거임!

SELECT *
FROM (SELECT T.*,ROWNUM RN FROM
(SELECT * FROM EMP ORDER BY hiredate DESC)T)
WHERE RN BETWEEN 1 AND 3;                                         =>1~3 구간을 똑 잘라 온거

 

문제5-1)EMP테이블에서 부서 코드가 30인 직원중에 연봉 높은 순서로 위에서부터 3명을 출력하여라
       출력시 컬럼은 이름,연봉,직책,부서코드를 출력하여라.    

SELECT

FROM(SELCT T.* ROWNUM RN FROM

(SELECT ENAME,SAL,JOB,DEPTNO FROM EMP WHERE DEPTNO = 30 OERDER BY SAL DESC)T

WHERE RN BETWEEN 1 AND 3;

 

문제 5-2) 5-1에서 부서명 추가

SELECT *

FROM(SELCT T.*, ROWNUM RN FROM

(SELECT ENAME,SAL,JOB,DEPTNO ,DNAME

 FROM EMP E JOIN DEPT D ON E.DEPTNO=D.DEPTNO  WHERE DEPTNO = 30 OERDER BY SAL DESC)T

WHERE RN BETWEEN 1 AND 3;

문제 5-3) 모든사람 정렬 6~10번째인 사람들 출력 후 입사일,부서명 추가

 

 

최종보스

HR 계정에서 이름,연봉,입사일,부서명 ,도시명 출력! 입사일 기준으로 위에서 5명만

SELECT *

FROM(SELECT T.* , ROWNUM RN FROM

(SELECT FIRST_NAME,SALARY,HIRE_DATE,DEPARTMENT_NAME,CITY

FROM EMPLOYEES E JOIN DEPARTMENTS D ON D.DEPARTMENT_ID = E.DEPARTMENT_ID 

JOIN LOCALTIONS L ON L.LOCATION_ID = D.LOCATION_ID

ORDER BY HIRE_DATE DESC)T)

WHERE RN BETWEEN 1 AND 5;

역시

SELECT*FROM(SELECT T.*, ROWNUM RN FROM(  여기만 조건에 맞게 SELCT절 FROM절 JOIN ORDER BY 바꿔 )T) WHERE RN BETWEEN 11 AND 20

이 틀만 외우면 무적임 !!! 

 

++ 보너스 문제

역시 HR계정에서 사원들 연봉순으로 나열후 11~20까지만 출력

그리고 이름(LAST_NAME || FIRST_NAME), 연봉, 부서명 , 도시명 출력하라

 

'학원 > DB(오라클),SQL문' 카테고리의 다른 글

10/18 23-2 테이블 변경  (1) 2022.10.18
10/18 23-1 테이블 생성  (0) 2022.10.18
10/17 22-1 JOIN  (0) 2022.10.17
오라클 INNER JOIN 수정  (0) 2022.10.17
10/14 21-1 오라클 시작  (1) 2022.10.14

+ Recent posts