일단 진행시켜

[JOIN] RDBMS의 궁극적 목적 본문

🗄️Data Base 아는 것도 다시보자

[JOIN] RDBMS의 궁극적 목적

2024. 8. 4. 23:10

1. JOIN

RDBMS를 사용하는 궁극적 목적

 

INNER JOIN 두 테이블의 교집합
LEFT/RIGHT (OUTER) JOIN 1개 테이블에만 데이터가 있어도 조회 됨(반대 테이블은 NULL로 출력)
OUTER는 붙든 안 붙든 똑같음
FULL OUTER JOIN 전체 집합

 

 

가볍게 JOIN 실습해 보자

 

INNER JOIN -1: 전공 code가 컴퓨터공학(COMENG)인 여학생 이름 출력

JOIN = INNER JOIN(default)

 

 

INNER JOIN -2: 엠비티아이에 S나 P가 들어간 학생 이름, 생년월일, 엠비티아이 출력

 

 

여기까진 너무 간단하다.

다른 스키마를 활용하여 다양한 JOIN을 실습해 보자.

 

 

LEFT (OUTER) JOIN -1: 학생 중 하나의 수강과목도 선택하지 않은 학생 ID와 이름 조회

select s.student_id, s.student_name from student s
left join student_course sc on sc.student_id = s.student_id
where sc.course_id is null;

 

여기서는 LEFT JOIN을 사용해주어야 한다.

INNER JOIN은 교집합(둘 다 일치할 때)만 반환하기 때문에, is null이 먹히질 않는다.

LEFT JOIN을 사용해서 student 테이블 기준 모든 값 + 오른쪽 테이블의 일치하는 값을 가져오도록 한다.

 

LEFT (OUTER) JOIN -2: 학생의 이름, 수강한 과목과 교수 이름 조회 (단, 교수가 배정되지 않은 과목도 포함)

select s.student_name, c.course_name, p.professor_name from student s
left outer join student_course sc on sc.student_id = s.student_id
left outer join course c on sc.course_id = c.course_id
left outer join professor p on p.professor_id = c.professor_id;

 

학생 과목 테이블과의 조인 ➡️ 수강과목을 선택하지 않은 모든 학생이 결과에 포함됨

과목 테이블과의 조인 ➡️ 과목에 등록되지 않은 모든 과목이 결과에 포함됨(사실 말이 안 되지만.. 논리적으로 일관성..)

교수 테이블과의 조인 ➡️ 교수가 배정되지 않은 과목도 결과에 포함 됨

 

논리적으로 일관성을 맞추어 해당 결과를 출력할 수 있다.

 

 

 

 

FULL OUTER JOIN -1: 교수와 과목의 전체 내역 조회 (단, 교수 중 강의를 하지 않거나, 아직 교수가 배정되지 않은 과목도 모두 포함하여 추출)

select s.student_id, s.student_name from student s
left join student_course sc on sc.student_id = s.student_id
where sc.course_id is null;

 

교수 테이블과 과목 테이블 모두 서로와 관계없이 추출해야 하므로 FULL OUTER JOIN을 사용한다.

 

 

 

 

 

혼합 실습 1 : 컴퓨터공학과 여학생 혈액형별 평균 나이가 24살 미만인 혈액형과 평균 나이를 조회

 

1. 컴퓨터공학과 여학생 구하기

SELECT *
FROM tst_stdntinfo_m s
JOIN tst_stdntdptmt_i d ON s.stnb = d.stnb
WHERE s.stdntgndr_typ = 'F'
AND d.dptmt_cd = 'COMENG'

컴퓨터공학과 여학생의 모든 정보가 출력된다.

 

 

2. 혈액형별 컴퓨터공학과 여학생 구하기(?)

SELECT s.STDNTBLD_TYP
FROM tst_stdntinfo_m s
JOIN tst_stdntdptmt_i d ON s.stnb = d.stnb
WHERE s.STDNTGNDR_TYP = 'F'
AND d.dptmt_cd = 'COMENG'
GROUP BY s.stdntbld_typ

이렇게 하면 혈액형 4개가 각각 출력된다.

 

 

3. [결과] 혈액형별 평균나이가 24살 미만인 혈액형과 평균 나이를 조회

SELECT s.STDNTBLD_TYP, AVG(YEAR(curdate()) - YEAR(s.stdntbth_day)) as avg_age
FROM tst_stdntinfo_m s
JOIN tst_stdntdptmt_i d ON s.stnb = d.stnb
WHERE s.STDNTGNDR_TYP = 'F'
AND d.dptmt_cd = 'COMENG'
GROUP BY s.stdntbld_typ
HAVING avg_age < 24;

 

나이는 현재 YEAR에서 태어난 년도를 빼주면 구할 수 있다.

curdate()는 현재 년도를 반환하는 메서드다.

 

혈액형별 조회이므로 group by s.stdntbld_typ을 해주고, 

group by절 조건으로 평균 나이 제약이 있었으니 이를 having절에 추가해 준다.

 

 

group by는 동일한 값을 가진 컬럼을 기준으로 그룹별 연산을 적용할 때 사용한다. 집계함수와 함께 자주 사용된다.

having은 group by절의 값 중 원하는 조건을 걸고 싶을 때 사용한다.

혈액형별 "평균 나이가 24살 미만" >> 이 조건이 having절에 포함된다.