MySQL

MySQL JOIN

ryeonng 2024. 6. 7. 17:29

조인(Join)

데이터베이스에서 조인(Join)은 두 개 이상의 테이블에서 관련된 데이터를 결합해 새로운 결과를 생성할 때 사용하는 중요한 연산

 

Join이 필요한 이유

데이터베이스에서 정보는 중복을 최소화하고 효율적으로 저장하기 위해 여러 테이블에 분산되어 저장.
실제로 정보를 사용할 때는 여러 테이블에 흩어져 있는 데이터를 통합해야 할 필요가 발생한다.
예를 들면, 어떤 학생이 어떤 수업을 듣고 있는지 알고 싶을 때 '학생' 테이블과 '수업' 테이블을 결합해야만 필요한 정보를 얻을 수 있다.
복잡한 질의를 수행하기 위해서는 종종 여러 테이블의 데이터를 결합하고 비교해야 한다.
조인을 사용하면 이러한 요구사항을 효과적으로 처리할 수 있다.

 

조인은 데이터베이스에서 분산된 정보를 효과적으로 통합하여 사용자가 원하는 특정 정보를 얻기 위한 강력한 도구이다.

 

 

항상 먼저 접근하는 테이블이 기준이 되고, 위 그림에서 왼쪽 동그라미에 해당한다.

  • Join은 크게 INNER JOINOUTER JOIN 으로 분류된다.
  • INNER JOIN은 조건에 해당하는 데이터만 뽑아낸다.
  • OUTER JOIN 에는 다음과 같이 분류되지만, MySQL에서는 FULL OUTER JOIN을 지원하지 않는다.
    • LEFT OUTER JOIN
    • RIGHT OUTER JOIN
    • FULL OUTER JOIN (MySQL에서는 지원 X)

 

시나리오 1

 

학생 (tb_stduent)

컬럼명
데이터 타입
제약사항
제약사항 설명
no
INT
NOT NULL, PRIMARY KEY
고유 식별자, NULL 값 불허
name
VARCHAR(20)
NOT NULL
학생 이름, NULL 값 불허
gender
ENUM('F', 'M')
NOT NULL
성별, 'F' 또는 'M'만 가능, NULL 값 불허
grade
CHAR(1)
FOREIGN KEY REFERENCES tb_grade(grade)
다른 테이블의 기본키 참조, 학년 정보

 

 

성적 등급 (tb_grade)

컬럼명
데이터 타입
제약사항
제약사항 설명
grade
CHAR(1)
PRIMARY KEY
학년, 고유 식별자로 기본키 설정
score
INT
 
점수, 별도의 제약사항 없음

 

create table tb_student(
	no int primary key not null,
    name varchar(20) not null,
    gender enum('F','M') not null,
    grade char(1),
	foreign key(grade) references tb_grade(grade)
);

create table tb_grade(
	grade char(1) primary key,
    score int
);

-- 테이블은 정보의 최소 단위이다.
insert into tb_grade values('A',100);
insert into tb_grade values('B',80);
insert into tb_grade values('C',60);
insert into tb_grade values('D',40);
insert into tb_grade values('E',20);
insert into tb_grade values('F',0);

-- ---------------------------------
select * from tb_grade;
select * from tb_student;
-- ---------------------------------

-- 오류 발생 : 아래에서 스키마 추가 (age 컬럼)
-- insert into tb_student(no, name, gender, grade, age) values('100', '길동', 'F', 25, 'B');

-- 스키마 구조 변경 필요 (age 컬럼 추가)
alter table tb_student add age int;
insert into tb_student(no, name, gender, grade, age)
	values ('100', '길동', 'F', 'A', 35);
    
    insert into tb_student(no, name, gender, grade, age)
	values ('200', '둘리', 'M', 'B', 25);
    
    insert into tb_student(no, name, gender, grade, age)
	values ('300', '마이콜', 'F', 'B', 15);
    
    insert into tb_student(no, name, gender, grade, age)
	values ('400', '야스오', 'M', 'C', 25);
    
    insert into tb_student(no, name, gender, grade, age)
	values ('500', '티모', 'F', 'E', 25);

 

주의

MySQL에서 JOIN, CROSS JOIN, INNER JOIN은 구문적으로 동등하다. 결과가 같고, 서로 대체가 가능하다.
( 표준 SQL에서는 동일하지 않다. 보통 INNER JOIN은 ON절과 함께 쓰이고, CROSS JOIN은 다르게 사용된다. CROSS JOIN이란 한 쪽 테이블의 행 하나에 다른 쪽 테이블의 행을 각각 조인시키는 걸 말한다.)
ON 조건 없이 사용하게 되면 CROSS JOIN의 결과가 나오고, ON 조건을 사용하게 되면 조건을 건 컬럼의 값이 같은 데이터들을 합친 결과가 나온다.

MySQL에서는 JOIN 또는 INNER JOIN을 할 때, ON으로 조건을 지정해주지 않으면 CROSS JOIN의 결과가 나온다.

 

 -- JOIN 연산에 ON 절 사용하지 않아보기 !
    -- CROSS JOIN이 된다. 
    select *
    from tb_student
    join tb_grade;
    
    select *
    from tb_grade
    join tb_student;
    
    -- 조인 연산은 가능한 ON 절과 함께 사용하자.
    -- JOIN : INNER JOIN / OUTER JOIN 이 존재
    -- 		  INNER JOIN : 그냥 JOIN 이라고도 한다. 
    
    -- 1단계
    select *
    from tb_student -- 먼저 접근하는 테이블
    join tb_grade on tb_student.grade = tb_grade.grade;
    
    -- 2단계 : 필요한 부분만 가져오기
    select s.no, s.name, s.grade, s.age, g.score
    from tb_student as s -- 별칭 만들기
    join tb_grade as g
    on s.grade = g.grade;

 

 


 

OUTER JOIN

LEFT JOIN ( = LEFT OUTER JOIN )

왼쪽 테이블을 기준으로 합치며, ON 절에 있는 조건 컬럼의 값이 같은 데이터를 합친다. 오른쪽 테이블에 값이 같은 데이터가 없다면, NULL이 삽입된다.

 

-- 1단계 
select *
from tb_student as s
left join tb_grade as g
on s.grade = g.grade;

-- 2단계
select *
from tb_grade as g
left join tb_student as s
on g.grade = s.grade;
-- student에서 grade A 와 D 를 받은 학생은 한 명도 없다.

 

LEFT JOIN 먼저 접근 하는 테이블이 기준 테이블이 된다.

 

 

LEFT JOIN ( = LEFT OUTER JOIN )

오른쪽 테이블을 기준으로 합치며, 나머지 부분은 LEFT JOIN과 같다.

-- RIGHT OUTER JOIN
select *
from tb_student as s
right join tb_grade as g
on s.grade = g.grade;

'MySQL' 카테고리의 다른 글

MySQL Function  (0) 2024.06.07
테이블 복사 및 데이터 추가  (0) 2024.06.07
관계 차수  (5) 2024.06.07
인덱스(index)  (0) 2024.06.05
UNIQUE 제약  (0) 2024.06.04