종류
예시
지금까지는 테이블 전체에 대하여 집계함수를 적용하였다.
전체 테이블을 특정 속성 값으로 터플을 분류하고,
나누어진 각 그룹에 대하여 집계 함수를 적용하는것이 Group by
Select deptName, count(*) // 3. subgroup 별로 모든 Tuple의 숫자를 셈
from professor // 1. professor 테이블에서
group by deptName; // 2. 학과별로 subgroup 나눈뒤
Select deptName, avg(salary) // 3. 각 그룹에 대해 salary 들의 평균을 구한다.
from professor // 1. professor 테이블에서
group by deptName; // 2. 학과별로 subgroup을 나눈뒤에
주의사항
”group by“ 절을 사용할 때, select절에는 ”group by“ 절에 나온 속성과 그 집계 함수만 나올 수 있다
// wrong code
Select deptName, pID, avg(salary)
from professor
group by deptName; // pID가 없으므로 에러
그룹당 deptName과 집계함수값이 생성되는것에 반하여, PID값은 그룹 수보다 많이 존재해야 해서 보여줘야하는 pID값을 선정할 수 없다.
Select avg(salary) // 3. 각 그룹에 대해 salary 들의 평균을 구한다.
from professor // 1. professor 테이블에서
group by deptName; // 2. 학과별로 subgroup을 나눈뒤에
다만, 어떤 그룹에 대한 평균값인지 알 수 없게 된다.
(7000, 6500, 7500)만 반환됨.
“group by” 절 결과로 생성된 그룹에 대하여 임의 조건을 명시하는데 사용된다
- 전제조건 : group by 와 함께 사용
- having과 where절은 다르게 사용된다
Find the names and average salaries of all departments whose average salary is greater than 6900
Select deptName, avg(salary)
from professor
group by deptName
having avg(salary) > 6900;
// wrong version
Select dname, count(*)
from department, empoloyee
where dnumber=dno and salary>40000
group by dname
having count(*)>5;```
// correct version
Select dname, count(*)
from department, employee
where dnumber=dno and salary>40000 and
dno in (select dno from employee
group by dno
having count(*)>5)
group by dname;
기본적으로 Null값은 무시
- select절 내 subquery : select 문장의 결과는 테이블이므로 select 문장에서 테이블이 위치하는 장소에는 select-from-where 표현이 이론적으로 가능
- 보통 subquery : 보통 중첩 질의문은 where절 또는 from절에 위치하고 있다.
특수한 경우(=결과테이블에 값이 하나만 존재할 때) 가능한 케이스
Select name
from professor
where salary = (select salary
from professor
where pID='10')
and pID <> '10'; // 다른 당사자 제외
Select name
from professor
where salary = (select max(salary)
from professor
where deptName='CS');
바람직하지 않은 query. = 으로 비교하려면, 동등해야하는데 ‘salary’ 자체랑 동등하려면
Salary는 값 하나고, select의 결과물은 테이블(집합)이므로 값과 집합이 같다는걸 비교해야함.
특수한 상황에서만 비교 가능 (집합에 값 하나만 있을경우 = Single-row subquery )
// ver1
Select distinct cID
from teaches
where semester='Fall' and year=2009 and
cID in (select cID from teaches
where semester='Spring' and year=2010);
// ver2
(select cID from teaches where semester='Fall\ and year = 2010) intersect (select cID from teaches where semester='Fall' and year=2009)
Select distinct cID
from teaches
where semester='Fall' and year=2009 and cID not in (select cID from teaches where semester = 'Spring' and year=2010);
// ver.1
// () = 임시로 튜플을 생성하는 연산자
Select count(distinct sID)
from takes
where (cID, semester, year) in (select cID, semester, year
from teaches
where pID=10);
// ver.2
Select count(distinct sID)
from takes, teaches
where pID='10' and teaches.cID=takes.cID and teaches.semester=takes.semester and teacehs.year=takes.year