workspace/backend
과제2. SQL Basic 작성해보기 (피드백 있음)
HwangJerry
2023. 9. 15. 13:30
Q. 아래 표를 참고하여 다음 물음에 답하시오.
Q1. 5번 부서에서 근무하고, 급여(salary)가 30000 이상인 모든 직원의 성명(Fname, Lname)을 검색하라.
SELECT Fname, Lname
FROM Employee
WHERE Dno = 5
AND salary >= 30000;
결과:
Fname | Lname |
John | Smith |
Franklin | Wong |
Ramesh | Narayan |
Q2. ‘ProductX’ 프로젝트에서 주당 10시간 이상 작업한 5번 부서에서 근무하는 모든 직원의성명(Fname, Lname)을 검색하라.
SELECT Fname,Lname
FROM PROJECT , WORKS_ON, EMPLOYEE
WHERE EMPLOYEE.Ssn = WORKS_ON.Essn
AND Hours >= 10
AND WORKS_ON.Pno=PROJECT.Pnumber
AND Project.Pname= 'ProductX'
And Dno=5;
결과:
Fname | Lname |
John | Smith |
Joyce | English |
Q3. 자신과 동일한 이름(Fname)을 가진 부양가족(dependent)이 있는 직원의 성명(Fname, Lname) 을 모두 검색하라.
SELECT Fname, Lname
FROM Employee, Dependent
WHERE Employee.Ssn = dependent.Essn
AND dependent.Dependent_name = employee.Fname;
결과: null
Q4. ‘Franklin Wong’이 직접 관리하는 직원의성명(Fname, Lname) 을 모두 검색하라.
SELECT E.Fname, E.Lname
FROM Employee as E, Employee as S
WHERE S.Fname = 'Franklin'
AND S.Lname = 'Wong'
AND S.Ssn = E.Super_ssn;
결과:
Fname | Lname |
John | Smith |
Ramesh | Narayan |
Joyce | English |
Q5. ‘Research’ 부서에서 근무하는 모든 직원의 성명(Fname, Lname) 을 검색하라. 단, 3번 프로젝트에 참가하고 있는 직원은 제외하도록 한다.
SELECT Fname, Lname
FROM Employee, Department, Project
WHERE Employee.Dno = Department.Dnumber
AND department.Dname = 'Research'
AND Department.Dnumber = Project.Dnum
AND Project.Pnumber not in (3);
결과:
Fname | Lname |
John | Smith |
Joyce | English |
-> 5번에 대한 피드백:
위 쿼리는 3번 프로젝트에 참여하는 부서를 제외한 것이다.
문제는 3번 프로젝트에 참여하는 직원을 제외하라고 했으므로 아래와 같이 쿼리를 구성해야 한다.
select fname, lname
from employee, department
where dno=dnumber and dname = 'research'
minus
select fname, laname
from employee, works_on
where pno=3 and essn = ssn;
위 쿼리 중 minus 아래 부분은 AND Ssn NOT IN {'666884444', '333445555'} 와 같은 효과이며, 저 ssn은 select essn from workds_on where pno = 3;인 쿼리를 저 {} 안에 넣어주면 된다.
(MINUS는 지원하지 않는 DBMS가 있다.)
SELECT Fname, Lname
FROM Employee, Department
WHERE Dname = 'Research' AND
Dno = Dnumber AND
ssn not in (SELECT essn FROM works_on WHERE pno =3);
즉, not in 뒤에 works_on 테이블에 대한 데이터를 검열한 뒤에 not in 으로 처리하게 되므로, works_on테이블을 굳이 FROM 뒤에 넣거나 WHERE 뒤에 조건을 달아서 join을 발생시킬 필요가 없다.
데이터베이스 연산 중에서 JOIN 연산이 비용이 가장 비싸다.
따라서, 조인은 최소화할 수 있다면 최소화하는 것이 합리적인 선택이다.
하지만, DBMS의 query optimizer가 선언된 join을 더 효율적인 join 방식으로 최적화할 순 있지만, not in {} 내부의 서브쿼리를 넣어버리면 DBMS는 해당 부분을 최적화할 수 없어 냅다 실행할 수 밖에 없다. 따라서 DBMS의 쿼리 작성 가이드를 보면 일반적으로 nested query는 사용하지 말라는 문구를 확인할 수 있다.
+++
만약 동명이인이 있을 경우에는 의도치 않은 연산 결과를 얻을 수 있으므로, select 뒤에 유일한 값을 갖는 칼럼을 설정해주면 해당 문제를 방지할 수 있을 것이다.