일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 김영한
- Extendable hashing
- 인터럽트
- 코딩애플
- 프로세스 주소 공간
- 운영체제와 정보기술의 원리
- 네트워크
- 쉬운코드
- 온디바이스AI
- 시스템프로그래밍
- 개발남노씨
- 코딩테스트 [ ALL IN ONE ]
- BreadcrumbsComputer-Networking_A-Top-Down-Approach
- SQL
- 백엔드
- recoverability
- vite
- 운영체제
- 커널 동기화
- concurrency control
- 데이터베이스
- 갤럭시 S24
- 트랜잭션
- CPU 스케줄링
- B tree 데이터삽입
- Git
- 시그널 핸들러
- SDK
- 쉬운 코드
- 반효경
- Today
- Total
티끌모아 태산
⭐️SQL 데이터 조회: subquery 본문
이번시간에는 SQL에서 subquery를 통해 다양한 조건으로 데이터를 조회하는 방법에 대해서 배워 subquery와 관련된 대표적으로 중요한 기본기들을 익혀보겠습니다.
subquery
- ID가 14인 임직원보다 생일이 빠른 임직원의 ID, 이름, 생일을 알고싶다.-> employee table 참조
SELECT birth_date FROM employee WHERE id = 14;
우선, ID가 14인 임직원의 생일을 파악한다. -> 예를들어 result: 1992-08-04 라 했을 때, 다음과 같이 작성하면 된다.
SELECT id, name, birth_date FROM employee WHERE birth_date < 1992-08-04;
❗️이때, SELECT 문을 두 번 작성하게 되는데, 이를 한번에 처리할 수 있을까? 두 번째 SELECT문의 1992-08-04는 결국 첫번 째 SELECT문의 결과값이기 때문에 첫번 째 SELECT문을 두번 째 SELECT문에 넣어보자 -> subquery!
SELECT id, name, birth_date FROM employee WHERE birth_date < (
SELECT birth_date FROM employee WHERE id = 14
);
위 코드에서 "SELECT birth_date FROM employee WHERE id = 14;" 이게 subquery가 된다. 그리고 이 서브 쿼리를 포함하는 "SELECT id, name, birth_date FROM employee WHERE birth_date < 1992-08-04;" 이 코드를 outer query 즉 메인 쿼리라고 부른다.
- ID가 1인 임직원과 같은 부서 같은 성별인 임직원들의 ID와 이름과 직군을 알고 싶다.-> employee table 참조
SELECT id, name, position FROM employee WHERE (dept_id, sex) = (
SELECT dept_id, sex FROM employee WHERE id = 1;
);
- ID가 5인 임직권과 같은 프로젝트에 참여한 임직원들의 ID를 알고 싶다. 이때, 결과 테이블에 중복된 튜플을 제외하고 싶다. -> works_on table 참조
SELECT proj_id FROM works_on WHERE empl_id = 5;
이렇게 id 가 5인 임직원이 참여한 프로젝트의 id를 먼저 찾는다. 그리고 그 임직원과 함께 참여한 임직원들의 id를 찾는다. 결과가 2001, 2002라 할 때,
SELECT DISTINCT empl_id FROM works_on WHERE empl_id != 5 AND (proj_id = 2001 OR
proj_id = 2002
);
이때, 2001과 2002 모두 참여한 사람들도 포함하게 되는 경우 중복이 발생하기 때문에 DISTINCT를 사용하였습니다.
코드를 더 간단 명료하게 작성하면 다음과 같다.
SELECT DISTINCT empl_id FROM works_on WHERE empl_id != 5 AND proj_id IN (
SELECT proj_id FROM works_on WHERE empl_id = 5
);
여기서, SET은 중복을 허용하지 않고 multiset은 중복을 허용한다.
SELECT DISTINCT empl_id FROM works_on WHERE empl_id != 5 AND proj_id IN (
SELECT proj_id FROM works_on WHERE empl_id = 5
);
이말은 "SELECT proj_id FROM works_on WHERE empl_id = 5" 여기서 empl_id는 메인쿼리의 works_on이 아닌 서브쿼리의 works_on 테이블을 참조하고, 메인 쿼리에서 eml_id와 proj_id는 메인쿼리의 works_on 테이블을 참조한다는 뜻이다.
💡만약 여기서 추가로 임직원의 id뿐만 아니라 이름도 알고 싶으면 어떻게 해야할까? -> employee, project tables 참조
SELECT id, name FROM employee WHERE id IN (
SELECT DISTINCT empl_id FROM works_on
WHERE empl_id != 5 AND proj_id IN (
SELECT proj_id FROM works_on WHERE empl_id = 5)
);
- ID가 7 혹은 12인 임직원이 참여한 프로젝트의 ID와 이름을 알고 싶다.-> project, works_on tables 참조하고 IN과 EXISTS 두 가지 방식으로 모두 풀어보기
SELECT P.id, P.name FROM project (AS) P
WHERE EXISTS (SELECT * FROM works_on W
WHERE W.proj_id = P.id AND W.empl_id IN (7, 12)
);
EXISTS -> 원하는 정보를 조회해서 있으면 TRUE.
EXIST 와 IN 을 서로 바꿔가면서 사용할 수 있습니다!
- 2000년대생이 없는 부서의 ID와 이름을 알고 싶다. -> department, employee tables 참조, NOT EXIST, NOT IN 두가지 방식으로 모두 풀어보기
SELECT D.id, D.name FROM department D WHERE NOT EXIST (
SELECT * FROM employee E WHERE E.dept_id = D.id AND
E.birth_date >= '2000-01-01'
);
이 코드를 다시 NOT IN 으로 바꿔보자.
- 리더보다 높은 연봉을 받는 부서원을 가진 리더의 ID와 이름과 연봉을 알고 싶다. -> department, employee tables 참조, ANY
SELECT E.id, E.name, E.salary FROM department D, employee E
WHERE D.leader_id = E.id AND E.salary < ANY (
SELECT salary FROM employee
WHERE id != D.leader_id AND dept_id = E.dept_id
);
💡만약 리더보다 높은 연봉을 받는 부서원을 가진 리더의 ID와 이름과 연봉과 해당 부서 최고 연봉을 알고 싶다.
SELECT E.id, E.name, E.salary, (
SELECT max(salary)
FROM employee
WHERE dept_id = E.dept_id -- 리더와 같은 부서의 임직원을 의미
) AS dept_max_salary -- 결과를 dept_max_salary라고 별칭을 지어줌.
FROM department D, employee E WHERE D.leader_id = E.id AND E.salary < ANY (
SELECT salary FROM employee WHERE id != D.leader_id AND dept_id = E.dept_id
)
이 예제를 통해 서브 쿼리가 SELECT에도 속할 수 있음을 보여준다.
- ID가 13인 임직원과 한번도 같은 프로젝트에 참여하지 못한 임직원들의 ID, 이름, 직군을 알고 싶다. 이때, 중복된 튜플은 제거한다-> ALL, employee, works_on tables 참조
SELECT DISTINCT E.id, E.name, E.position
FROM employee E, works_on W
WHERE E.id = W.empl_id AND W.proj_id != ALL (
SELECT proj_id
FROM works_on
WHERE empl_id = 13
);
'CS 지식 > 데이터베이스' 카테고리의 다른 글
SQL로 데이터 조회하기, NULL (0) | 2023.09.16 |
---|---|
SQL 데이터 조회 (0) | 2023.09.10 |
⭐️SQL을 통한 데이터 추가, 수정, 삭제 (1) | 2023.09.08 |