BASHA TECH

DB#CH06. 조인과 서브쿼리 이해 본문

Computer/DB

DB#CH06. 조인과 서브쿼리 이해

Basha 2022. 7. 29. 16:08
728x90

1. 조인의 종류

2. 내부 조인과 외부 조인

3. ANSI 조인

4. 서브 쿼리

 

1. 조인의 종류

    : 사실 내부 조인과 외부 조인만 구분할 수 있음 됨... 

- 조인 연산자에 따른 구분: 동등 조인, 안티 조인

- 조인 대상에 따른 구분: 셀프 조인 => 2개 테이블을 연결... 근데 본인 테이블을 연결하는...

- 조인 조인에 따른 구분: 내부조인&외부조인, 세미 조인, 카타시안 조인

- ANSI 조인

 

2. 내부 조인과 외부 조인

내부 조인 - 동등 조인, 안티 조인, 세미 조인

외부 조인 - 내부 조인이 아닌 모든 것... 결과 set의 밖을 가져온다.

▶ 내부 조인의~

- 동등 조인

   : WHERE 절(where절의 기능은 row 선택)에서 등호(=) 연산자를 사용해 2개 이상의 테이블이나 뷰를 연결한 조인 값을         비교한다.

SELECT DISTINCT b.PERIOD
	FROM KOR_LOAN_STATUS b
;

--문제 : 연도별 그룹화.
SELECT SUBSTR(b.PERIOD,1,4) AS years
		 , SUM(b.LOAN_JAN_AMT) AS tot_jan
	FROM KOR_LOAN_STATUS b
 GROUP BY SUBSTR(b.PERIOD,1,4)
 ORDER BY years
;
-- GROUP BY에서는 AS(alias) 사용 불가
-- 연도별 총 합
-- *이 있으면 GROUP BY


-- 문제: 사원번호(사번 | employees), 이름(employees), 부서번호(부번 | employees, departments table), 부서명(departments table) 조회
SELECT COUNT(*)
		FROM EMPLOYEES e
				,DEPARTMENTS d
	WHERE e.DEPARTMENT_ID(+) = d.DEPARTMENT_ID
--	where X => 카티시안 조인
;
-- inner한 결과를 갖고 outer 하는 거임

SELECT COUNT(*) FROM EMPLOYEES a;
--result: 107

SELECT COUNT(*) FROM DEPARTMENTS;
--result: 27

-- 모든 조인은 inner. inner한 결과에 따라 outer를 건다.

- 세미 조인

  : 서브 쿼리를 사용해 서브 쿼리에 존재하는 데이터만 메인 쿼리에서 추출

  > EXISTS 사용

-- 급여를 3000 이상 받는 사원이 존재하는 부서번호, 부서명 조회
SELECT d.DEPARTMENT_ID, d.DEPARTMENT_NAME
	FROM DEPARTMENTS d
	WHERE EXISTS ( -- WHERE절에 갖다 놓고 걸러내기만 하면 된다.. FROM 절은 nooo...~
	SELECT 1 --'x'
	  FROM EMPLOYEES e
	 WHERE e.salary > 3000
	 	AND e.DEPARTMENT_ID = d.DEPARTMENT_ID
	)
;

SELECT b.DEPARTMENT_ID, MAX(b.SALARY)
  FROM EMPLOYEES b
 GROUP BY b.DEPARTMENT_ID
 ORDER BY MAX(b.SALARY)
 ;

 -- select에 as 걸어도 되지만 order by에서 걸어줘도 됨...

SELECT b.DEPARTMENT_ID, MAX(b.SALARY) AS sal_max
  FROM EMPLOYEES b
 GROUP BY b.DEPARTMENT_ID
 ORDER BY sal_max, b.DEPARTMENT_ID
 ;

SELECT b.DEPARTMENT_ID
     , MAX(b.SALARY) AS sal_max
     , a.DEPARTMENT_NAME
  FROM EMPLOYEES b, DEPARTMENTS a
 WHERE b.SALARY > 10000
 	 AND a.DEPARTMENT_ID = b.DEPARTMENT_ID
 GROUP BY b.DEPARTMENT_ID, a.DEPARTMENT_NAME
 ORDER BY sal_max, b.DEPARTMENT_ID
 ;

-- 1row씩... employees에 있는 값을 쓸때없이 26번이나 연산 해야함. => 비효율. 시간 엄청 든다
-- exists 107개에서 걸러낸다. => 완전 효율. 시간이 적게 든다. 잘 생각해야함. . . . . . . . . . . . . . . . .........
-- ★★★★★ 진짜 진짜 중요~~~~~ 정확하게 인지하기~~~~~~~~ EXISTS EXISTS EXISTS!
-- 단, EXISTS를 쓸 땐 전제할 조건이 있다.. => FROM에 있는 것만 SELECT 해야할 때 EXISTS를 사용해야 함..
-- 세미 조인은 무조건 사용할 수 있는 건 아님. 안 그러면 스칼라 서브 쿼리를 사용해야함..

SELECT COUNT(a.DEPARTMENT_ID)
	FROM EMPLOYEES a
	WHERE a.SALARY > 3000
;

SELECT COUNT(a.EMPLOYEE_ID)
	FROM EMPLOYEES a
	WHERE a.SALARY > 3000
;

-- 문제 : 부서 별로 3000 이상 받는 사원 수는 몇명인가?
SELECT a.DEPARTMENT_ID
			,COUNT(a.DEPARTMENT_ID)
	FROM EMPLOYEES a
	WHERE a.SALARY >3000
	GROUP BY a.DEPARTMENT_ID
--	ORDER BY
;

SELECT a.DEPARTMENT_ID
			,COUNT(a.DEPARTMENT_ID) AS ecnt
	FROM EMPLOYEES a
	WHERE a.SALARY > 3000
	GROUP BY a.DEPARTMENT_ID
	ORDER BY ecnt
;

SELECT a.DEPARTMENT_ID
			,COUNT(a.DEPARTMENT_ID) AS ecnt
	FROM EMPLOYEES a
	WHERE a.SALARY > 3000
	GROUP BY a.DEPARTMENT_ID
	ORDER BY ecnt
;

  > IN 사용

- 안티 조인 : NOT IN, NOT EXISTS

- 셀프 조인 : 자기 자신 JOIN

- 외부 조인

  > 일반 조인

  > 외부 조인

- 카타시안 조인

 

3. ANSI 조인

더보기

Oracle JOIN :

 where - 조인 조건 (연결)

            - 조회 조건

ANSI JOIN :

 from - 조인, 조인 조건

 where - 조회 조건

- ANSI INNER JOIN

- ANSI OUTER JOIN

  > Left : LEFT <OUTER> JOIN

  > Right : RIGHT <OUTER>  JOIN

  > Full : FULL <OUTER> JOIN → (+) = (+)

- ANSI CROSS JOIN (Oracle Caratisian Join과 같다)

 

SELECT COUNT(DISTINCT a.employee_id)
	FROM EMPLOYEES a
	WHERE a.SALARY > 3000
;

SELECT a.DEPARTMENT_ID, a.DEPARTMENT_NAME
	FROM DEPARTMENTS a
	WHERE a.DEPARTMENT_ID IN (
				SELECT b.DEPARTMENT_ID
				FROM EMPLOYEES b
				WHERE b.SALARY >3000
	}
;

SELECT c.DEPARTMENT_ID
	FROM DEPARTMENTS c
;

SELECT b.DEPARTMENT_ID
	FROM EMPLOYEES b
	WHERE b.SALARY >3000
	ORDER BY b.DEPARTMENT_ID
;


SELECT d.DEPARTMENT_ID, d.DEPARTMENT_NAME
	FROM DEPARTMENTS d
	WHERE EXISTS ( -- WHERE절에 갖다 놓고 걸러내기만 하면 된다.. FROM 절은 nooo...~
	SELECT 1 --'x'
	  FROM EMPLOYEES e
	 WHERE e.salary > 3000
	 	AND e.DEPARTMENT_ID = d.DEPARTMENT_ID
	)
;
--

SELECT COUNT(a.DEPARTMENT_ID)
	FROM DEPARTMENTS a
		 , EMPLOYEES b
 WHERE a.MANAGER_ID IS NULL
   AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 사원이 존재하는 부서에서 부서장이 없는 절을 찾아라 => 0개.
   --즉, 사원이 존재하는 부서에서는 모두 부서장이 있다.
;

SELECT COUNT(a.DEPARTMENT_ID)
	FROM DEPARTMENTS a
--		 , EMPLOYEES b
 WHERE a.MANAGER_ID IS NULL
--   AND a.DEPARTMENT_ID = b.DEPARTMENT_ID
; -- 16개는 안 쓰는 부서

SELECT *
	FROM EMPLOYEES a
	WHERE a.DEPARTMENT_ID = 20
	ORDER BY a.EMPLOYEE_ID ASC
;

-- 사원 이름과 상사 이름 추출
SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.EMPLOYEE_ID, b.EMP_NAME
	FROM EMPLOYEES a
		 , EMPLOYEES b
 WHERE a. DEPARTMENT_ID = b.DEPARTMENT_ID
	 AND a.DEPARTMENT_ID = 20
;

SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.EMPLOYEE_ID, b.EMP_NAME
	FROM EMPLOYEES a
		 , EMPLOYEES b
 WHERE a. DEPARTMENT_ID = b.DEPARTMENT_ID
	 AND a.DEPARTMENT_ID = 20
	 AND a.EMPLOYEE_ID < b.EMPLOYEE_ID
;

SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.EMPLOYEE_ID, b.EMP_NAME
	FROM EMPLOYEES a
		 , EMPLOYEES b
 WHERE a. DEPARTMENT_ID = b.DEPARTMENT_ID
	 AND a.DEPARTMENT_ID = 60
	 AND a.EMPLOYEE_ID < b.EMPLOYEE_ID
;

-- 문제 : 60번 부서의 사원이름과 상사의 이름 추출
-- 한개 row에서 사원이름(emp_name), 상사사원번호(m_id)
-- 다른 테이블에서 사원번호(e_id) => 이름 => 상사의 이름
-- m_id = e_id
-- 1. 60번 부서 추출
SELECT a.DEPARTMENT_ID, a.MANAGER_ID
	FROM EMPLOYEES a
	WHERE a.DEPARTMENT_ID = 60
;
-- 2. 60번 부서 추출
-- Self join
SELECT COUNT(*)
	FROM EMPLOYEES a
		 , EMPLOYEES b
 WHERE a.DEPARTMENT_ID = 60 -- a는 5명, b는 107명 => 5 x 107 =535명 (카티시안 곱)
 	 AND b.DEPARTMENT_ID = 60 -- a는 5명, b는 5명 => 5 x 5 =25명
;
--
SELECT COUNT(*)
	FROM EMPLOYEES a
		 , EMPLOYEES b
 WHERE a.DEPARTMENT_ID = 60 -- a는 5명, b는 107명 => 5 x 107 =535명 (카티시안 곱)
 	 AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 조인 조건
	 AND a.MANAGER_ID = b.EMPLOYEE_ID
;

-- Outer Join
-- 문제 ?
SELECT a.DEPARTMENT_ID
		 , a.DEPARTMENT_NAME
		 , b.JOB_ID
		 , b.DEPARTMENT_ID
	FROM DEPARTMENTS a
	   , JOB_HISTORY b
 WHERE a.DEPARTMENT_ID = b.DEPARTMENT_ID
-- AND 올해 비교
;

SELECT a.DEPARTMENT_ID
		 , a.DEPARTMENT_NAME
		 , b.JOB_ID
		 , b.DEPARTMENT_ID
	FROM DEPARTMENTS a
	   , JOB_HISTORY b
 WHERE a.DEPARTMENT_ID = b.DEPARTMENT_ID(+)
-- AND 올해 비교
;

SELECT *
	FROM JOB_HISTORY a -- 이력
	WHERE a.EMPLOYEE_ID = 101
;
SELECT a.employee_id
     , a.DEPARTMENT_ID
     , a.JOB_ID
	FROM EMPLOYEES a -- 현재
 WHERE a.EMPLOYEE_ID = 101
;

--hola comment t'alleze vous

SELECT a.EMPLOYEE_ID
		 , a.EMP_NAME
     , b.JOB_ID
     , b.DEPARTMENT_ID
	FROM EMPLOYEES a
	   , JOB_HISTORY b
 WHERE a.EMPLOYEE_ID = b.EMPLOYEE_ID
--   AND a.DEPARTMENT_ID(현재부서) = b.DEPARTMENT_ID(예전부서) 현재부서와 과거부서가 같은 것 중 업무만 변경된 이력 조회
;

SELECT a.EMPLOYEE_ID
		 , a.EMP_NAME
		 , a.DEPARTMENT_ID -- 현재 부서
     , a.JOB_ID
     , b.JOB_ID
     , b.DEPARTMENT_ID
	FROM EMPLOYEES a
	   , JOB_HISTORY b
 WHERE a.EMPLOYEE_ID = b.EMPLOYEE_ID -- 변경 이력이 있는 사화
   AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 부서는 같은데 job id(변경이력)만 다른 경우
;

SELECT a.EMPLOYEE_ID
		 , a.EMP_NAME
		 , a.DEPARTMENT_ID -- 현재 부서
     , a.JOB_ID
     , b.JOB_ID
     , b.DEPARTMENT_ID
	FROM EMPLOYEES a
	   , JOB_HISTORY b
 WHERE a.EMPLOYEE_ID = b.EMPLOYEE_ID(+) -- 변경 이력이 있는 사화
--   AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 부서는 같은데 job id(변경이력)만 다른 경우
;

SELECT a.EMPLOYEE_ID
		 , a.EMP_NAME
		 , a.DEPARTMENT_ID -- 현재 부서
     , a.JOB_ID
     , b.JOB_ID
     , b.DEPARTMENT_ID
	FROM EMPLOYEES a
	   , JOB_HISTORY b
 WHERE a.EMPLOYEE_ID = b.EMPLOYEE_ID(+) -- 변경 이력이 있는 사화
   AND a.DEPARTMENT_ID = b.DEPARTMENT_ID(+) -- 부서는 같은데 job id(변경이력)만 다른 경우
;

SELECT a.EMPLOYEE_ID, a.EMP_NAME, a.DEPARTMENT_ID, a.JOB_ID
     , b.JOB_ID, b.DEPARTMENT_ID
  FROM EMPLOYEES a
     , JOB_HISTORY b
WHERE a.EMPLOYEE_ID = b.EMPLOYEE_ID(+)
  AND a.DEPARTMENT_ID = b.DEPARTMENT_ID(+)
;


INSERT INTO EMP(empno, empnm) VALUES(400, '희동'); 

-- emp, dept 
SELECT * FROM emp;
SELECT * FROM dept;
--100   홍길동   10 | 10   개발부
--200   고길동   20 | 20   총무부
--300   마이꼴   10 | 30   영업부
--400   희동   NULL

-- 문제 : 우리회사 모든 사원 조회 : 사원 번호, 사원명, 부서명
SELECT e.EMPNO, e.EMPNM, d.emptno, d.empnm
	FROM emp e
	    ,dept d
	WHERE e.DEPTNO = d.DEPTNO(+)
;

-- 문제 : 우리 회사의 모든 부서명 조회 : 사원 번호, 사원명, 부서명
-- 부서번호, 부서명 => 조인이 필요 없다.
SELECT e.EMPNO, e.EMPNM, d.DEPTNM
	FROM emp e
	   , dept d
 WHERE e.DEPTNO(+) = d.DEPTNO
;

SELECT *
	FROM EMPLOYEES a
	WHERE ROWNUM < 2
;

DESC EMPLOYEES;

-- 2012년 이후 입사 사원 조회
-- 2013년 1월 1일 이후 입사
SELECT *
	FROM EMPLOYEES a
 WHERE a.HIRE_DATE >= '2013-01-01 12:00:00' --CASE1. HIRE_DATE를 STR로 바꾸던지, CASE2. STR을 DATE로 바꾸던지
;
SELECT *
	FROM EMPLOYEES a
 WHERE TO_CHAR(a.HIRE_DATE, 'YYYY-MM-DD') >= '2013-01-01'
; -- 21-6

SELECT TO_CHAR(a.HIRE_DATE), a.HIRE_DATE
	FROM EMPLOYEES a
 WHERE ROWNUM < 2
;
SELECT TO_CHAR(a.HIRE_DATE), a.HIRE_DATE
	FROM EMPLOYEES a
 WHERE ROWNUM < 2
;

-- 전체 사원 중 가장 마지막에 입사한 사원 조회
-- HIRE_DATE 값이 가장 큰 값이 사원
SELECT MAX(a.HIRE_DATE)
	FROM EMPLOYEES a
;
SELECT MIN(a.HIRE_DATE) -- 가장 먼저 입사한 사람
	FROM EMPLOYEES a
;

-- 2006년 이후 입사 사원 조회
-- 2007년 1월 1일 이후 입사
SELECT *
	FROM EMPLOYEES a
 WHERE TO_CHAR(a.HIRE_DATE, 'YYYY-MM-DD') >= '2007-01-01'
;

-- 2 TO_DATE
SELECT *
	FROM EMPLOYEES a
	WHERE a.HIRE_DATE >= TO_DATE('2007-01-01', 'YYYY-MM-DD')
;

-- 2003년 1월 1일 이후(조회조건) 입사한 사원
-- 사원번호, 사원명, 부서명(조인조건) 조회
SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.DEPARTMENT_NAME
	FROM EMPLOYEES a
	   , DEPARTMENTS b
 WHERE a.HIRE_DATE >= TO_DATE('2003-01-01', 'YYYY-MM-DD') -- 조회 조건
	 AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 조인 조건
;

SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.DEPARTMENT_NAME
	FROM EMPLOYEES a
	   , DEPARTMENTS b
 WHERE a.HIRE_DATE >= TO_DATE('2003-01-01', 'YYYY-MM-DD') -- 조회 조건
	 AND a.DEPARTMENT_ID = b.DEPARTMENT_ID -- 조인 조건
;
--results: 17

-- ANSI Join
SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.DEPARTMENT_NAME
	FROM EMPLOYEES a
  INNER JOIN departments b
  	ON (a.DEPARTMENT_ID = b.DEPARTMENT_ID) -- 조인 조건
 WHERE a.HIRE_DATE >= TO_DATE('2007-01-01', 'YYYY-MM-DD')
;
SELECT a.EMPLOYEE_ID, a.EMP_NAME, b.DEPARTMENT_NAME
	FROM EMPLOYEES a -- Left
  JOIN departments b -- Right
  	ON (a.DEPARTMENT_ID = b.DEPARTMENT_ID)
 WHERE a.HIRE_DATE >= TO_DATE('2007-01-01', 'YYYY-MM-DD')
;
--results: 17

SELECT a.EMPLOYEE_ID
     , a.EMP_NAME
     , b.DEPARTMENT_NAME
--     , b.DEPARTMENT_ID => 이렇게 쓰면 에러
     , DEPARTMENT_ID
	FROM EMPLOYEES a
  JOIN departments b
--  	ON (a.DEPARTMENT_ID = b.DEPARTMENT_ID)
 USING (DEPARTMENT_ID) --USING 할 땐 column명만 기술하기, a. 하면 에러임
 WHERE a.HIRE_DATE >= TO_DATE('2007-01-01', 'YYYY-MM-DD')
;

SELECT a.EMPLOYEE_ID
     , a.EMP_NAME
     , b.DEPARTMENT_NAME
     , b.DEPARTMENT_ID -- using을 쓸거면 빼고 on절을 쓸 때는 같더라도 꼭 이렇게 써줘야 함.
	FROM EMPLOYEES a
  JOIN departments b
  	ON (a.DEPARTMENT_ID = b.DEPARTMENT_ID) --조인 조건
-- USING (DEPARTMENT_ID) --USING 할 땐 column명만 기술하기, a. 하면 에러임
 WHERE a.HIRE_DATE >= TO_DATE('2007-01-01', 'YYYY-MM-DD')
;

-- emp, dept 사용한 Outer Join
-- 모든 사원 조회: 사원번호, 사원명, 부서명
SELECT a.EMPNO, a.EMPNM, b.DEPTNM
	FROM emp a
	   , dept b
	WHERE a.DEPTNO = b.DEPTNO(+)
; -- Oracle
SELECT a.empno, a.empnm, b.deptnm
	FROM emp a
	LEFT JOIN dept b
		ON (a.deptno = b.deptno)
; -- ANSI

-- 모든 부서 조회: 사원번호, 사원명, 부서명
SELECT a.empno, a.empnm, b.deptnm
	FROM emp a
	   , dept b
 WHERE a.DEPTNO(+) = b.DEPTNO
;
SELECT a.empno, a.empnm, b.deptnm
	FROM emp a
	RIGHT JOIN dept b
		ON (a.deptno = b.deptno)
; -- ANSI

-- 우리 회사 모든 사원과 모든 부서 조회
-- 사원번호, 사원명, 부서명 추출
SELECT *
	FROM emp e
	   , dept d
 WHERE e.DEPTNO(+) = d.DEPTNO
UNION
SELECT *
	FROM emp e
	   , dept d
 WHERE e.DEPTNO = d.DEPTNO(+)
; --Oracle
SELECT a.EMPNO
		 , a.EMPNM
		 , b.DEPTNM
	FROM EMP a
	FULL JOIN DEPT b
		ON (a.DEPTNO = b.DEPTNO)
; -- ANSI

-- 최상위 부서(departments)에 속한 사원(employees) 수 추출
SELECT *
	FROM DEPARTMENTS a
	WHERE a.PARENT_ID IS NULL
;
SELECT a.DEPARTMENT_ID
	FROM DEPARTMENTS a
	WHERE a.PARENT_ID IS NULL
;
SELECT a.DEPARTMENT_ID, a.DEPARTMENT_NAME
	FROM DEPARTMENTS a
	WHERE a.DEPARTMENT_ID	= 10
;

-- 위 부서의 아래 부서 확인
SELECT *
	FROM DEPARTMENTS a
	WHERE a.PARENT_ID = 10
;

SELECT *
	FROM DEPARTMENTS a
 WHERE a.PARENT_ID = (
			SELECT a.DEPARTMENT_ID
			  FROM DEPARTMENTS a
			 WHERE a.PARENT_ID IS NULL
			)
;

SELECT DISTINCT a.PARENT_ID
	FROM DEPARTMENTS a
;

SELECT *
	FROM DEPARTMENTS a
	WHERE a.PARENT_ID = 100
;

SELECT *
	FROM DEPARTMENTS a
 WHERE a.PARENT_ID = (
			SELECT a.DEPARTMENT_ID
			  FROM DEPARTMENTS a
			 WHERE a.PARENT_ID = 100
			)
; --왜 에러가 날까? row 갯수가 안 맞아서 에러남

SELECT *
	FROM DEPARTMENTS a
 WHERE a.PARENT_ID IN ( -- IN은 다중값 연산자
			SELECT a.DEPARTMENT_ID
			  FROM DEPARTMENTS a
			 WHERE a.PARENT_ID = 100
			)
;

SELECT *
	FROM DEPARTMENTS a
 WHERE a.PARENT_ID IN ( -- =는 단일값만 IN은 다중값 연산자
			SELECT a.DEPARTMENT_ID
			  FROM DEPARTMENTS a
			 WHERE a.PARENT_ID IS NULL
			)
;

-- 최상위 부서 아래 부서의 개수 확인
SELECT COUNT(*)
	FROM DEPARTMENTS a
 WHERE a.PARENT_ID IN ( -- 상위 부서가 같은 부서
			SELECT a.DEPARTMENT_ID
			  FROM DEPARTMENTS a
			 WHERE a.PARENT_ID IS NULL -- 최상위 부서
			)
;

SELECT COUNT(*)
	FROM EMPLOYEES a
 WHERE a.DEPARTMENT_ID IN (
 			 SELECT b.DEPARTMENT_ID
 			 	 FROM DEPARTMENTS b
 			  WHERE b.PARENT_ID IS NULL
 			 )
 ;

SELECT COUNT(*)
	FROM EMPLOYEES a
 WHERE a.DEPARTMENT_ID = (  -- = 등호 하니까 이해하기가 더 명확해짐.
 			 SELECT b.DEPARTMENT_ID
 			 	 FROM DEPARTMENTS b
 			  WHERE b.PARENT_ID IS NULL
 			 )
 ;
-- SELECT COUNT(*) -- 사원 수
SELECT a.EMPLOYEE_ID, a.EMP_NAME -- 사원
	FROM EMPLOYEES a
 WHERE a.DEPARTMENT_ID = (
 			 SELECT b.DEPARTMENT_ID
 			 	 FROM DEPARTMENTS b
 			  WHERE b.PARENT_ID IS NULL
 			 )
 ;

-- SELECT COUNT(*) -- 사원 수
SELECT a.EMPLOYEE_ID, a.EMP_NAME -- 사원
 			,	b.DEPARTMENT_NAME -- b는 메인쿼리에 없으므로 에러임
	FROM EMPLOYEES a
 WHERE a.DEPARTMENT_ID = (
 			 SELECT b.DEPARTMENT_ID
 			 	 FROM DEPARTMENTS b
 			  WHERE b.PARENT_ID IS NULL
 			 )
 ;

 

 

728x90
반응형

'Computer > DB' 카테고리의 다른 글

수정할 거임 0802  (0) 2022.08.02
DB#CH05. 그룹 쿼리와 집합 연산자 이해  (0) 2022.07.28
DB#CH04. SQL 함수 이해  (0) 2022.07.27
DB#CH03. SQL 문장 이해  (0) 2022.07.26
DB#CH02. 데이터베이스를 구성하는 객체 이해  (0) 2022.07.26
Comments