Join 2개 이상의 테이블에서 쿼리를 작성하는 방법

테이블을 2개이상 조인한다는 의미

  • 잘 설계한 관계형 데이터베이스의 테이블은 1가지 이상의 엔티티entity를 포함한다.
    - e.g. DoItSQL 데이터베이스의 nasdaq_company 테이블에는 기업의 종목코드(symbol)나 기업 이름 (company_name)등의 정보가 저장되어 있고, stock 테이블에는 symbol에 따른 일별가격정보가 저장되어 있다

엔티티 Entity

엔티티는 저장되고 관리되어야 할 데이터로 (날짜나 종목코드등과 같은 식별자 정보)

일별 거래가를 검색할 때 기업 이름을 함께 표시하려면 어떻게 해야 할까?
테이블이 분리된 상황이므로 테이블의 데이터를 조합해야 할 것

  • 조인은 테이블 A의 열과 테이블 B의 정보를 포함해 검색할 수 있게 만들어 준다.

*데이터는 중복 저장 하지 않는다 : 저장할 공간이 더 필요한 문제, 중복 저자한 열 데이터를 수정할 경우 해당 열을 가진 테이블의 데이터를 모두 찾아 수정해야 하는 문제

데이터 중복을 최소화하는 설계는 피할 수 없으며 조인을 사용해 2개 이상의 테이블을 조합한 결과를 검색하는 방식이 효율적

  • 데이터 중복 없이 구성한 데이터 구조를 데이터 모델링에서는 '정규화 2단계'라고 한다
  • 반면 데이터를 중복해 저장하는 데이터 구조를 '반정규화' 또는 '역정규화 테이블'이라고 한다

데이터 모델링과 정규화

  • data modeling이란 주어진 상황에서 논리 데이터 모델을 구성하는 작업을 말한다.

  • 데이터 모델링이 끝나면 논리 데이터 모델을 물리 데이터 모델로 바꾼 다음 실제 데이터베이스에 반영하는 작업을 함

  • 정규화는 논리 데이터 모델의 중복을 제거해 일관성 있고 안정적인 자료구조를 만드는 단계임

  • 일반적으로 3차 정규화를 많이 사용
    - 데이터 모델이 적절한 일관성을 유지 하면서도 중복이 없는 노리 데이터 모델을 구성하는 것을 말한다


내부조인 INNER JOIN

  • 가장 많이 사용하는 조인

  • 조인키에 해당하는 각 테이블의 열값을 비교해 조건에 맞는 값을 검색

내부 조인의 기본 형식

SELECT [열 이름]
FROM [테이블 1]
INNER JOIN [테이블 2] ON [테이블 1.열] = [테이블 2.열]
WHERE [검색조건]

INNER JOIN VENN DIAGRAM


왼쪽은 고객 테이블 | 오른쪽은 주문 테이블

  • 고객 테이블에는 고객 번호와 고객 이름이 저장되어 있음
  • 주문 테이블에는 주문 번호, 고객 번호, 주문 날짜가 저장되어 있음

고객의 주문 내열을 모두 확인 하려면?

고객 테이블과 주문 테이블을 조인 하되 고객 번호를 조인 조건으로 삼아야 한다

  • 결과를 보면 inner join으로 두 테이블을 조합해 총 2건의 데이터를 검색했다.
  • 두 테이블의 고객번호가 서로 같은 0001과 0002에 해당하는 데이터만 조합해 검색
  • 그 결과 조인 조건이 고객 번호인 것도 알 수 있다

INNER JOIN문을 적용한 쿼리

SELECT
[고객.고객 번호], [고객], [고객 이름], [주문.주문 번호], [주문.고객 번호], [주문.주문 날짜]

FROM [고객]

INNER JOIN [주문] ON [고객.고객 번호] = [주문.고객 번호]


INNER JOIN문 사용하기

  • 조인은 2개 이상의 테이블을 전제로 하며, 실제 쿼리를 작성할 때는 SELECT 문에 다른 문을 추가하는 것이 아니라 FROM 문에 조인할 테이블을 나열 한다.

nasdaq_company 테이블과 stock 테이블을 INNER JOIN 문으로 조인해 symbol이 'MSFT'인 기업 정보와 해당 기업의 2021년 10월 일별 주가 데이터를 검색한 쿼리.

SELECT
a.symbol,
a.company_name,
a.ipo_year,
a.sector,
a.industry,
b.date,
b.[open],
b.[high],
b.[low],
b.[close],
b.adj_close,
b.volume
FROM nasdaq_company AS a
INNER JOIN stock AS b on a.symbol = b.symbol
WHERE a.symbol = 'MSFT'
AND b.date >= '2021-10-01'
AND b.date < '2021-11-01'

  • SELECT문에는 각 테이블에 검색할 열을 나열
    - 이때 테이블의 열 이름이 유일하다면 별칭을 사용하지 않아도 되지만 현재는 두 테이블에 같은 이름의 열이 있으므로 별칭을 사용
    • 만약 별칭을 사용하지 않으면 데이터베이스 엔진은 어떤 테이블의 열을 검색할지 판단할 수 없어 오류가 발생
  • FROM문에는 조인할 테이블 이름을 입력
    - 테이블 이름 뒤에 AS a라고 별칭을 붙임. 이는 'nasdaq_company 테이블을 a라고 부른다'라는 뜻
  • ON문은 테이블을 조인할 때 조인 조건으로 사용할 열을 지정
    - 이 예시에선 symbol열을 조인 조건으로 사용 : symbol열이 'MSFT'인 값만 검색 하도록 조건을 추가 함
  • 10월 데이터만 검색 : date조건에 날짜 연산 추가

ON문과 WHERE문의 차이

  • WHERE문은 조인을 완료한 상태에서 조건에 맞는 값을 가져오고자 사용
  • ON문은 조인할 때 조인 조건을 위해 사용

별칭을 사용 하지 않으면

  • 조인을 할 때 열 이름이 유일하지 않으면 데이터베이스 엔진은 무슨 테이블의 열을 검색해야 하는지 판단할 수 없으므로 오류

SELECT
symbol <<== 얘가 누군지 모름
FROM nasdaq_company AS a
INNER JOIN stock AS b ON a.symbol = b=symbol
WHERE a.symbol = 'MSFT'
AND b.date >= '2021-10-01'


INNER JOIN 문 사용하기 (2개 이상의 조건 적용)

  • 조인 조건으로 2개 이상의 열을 사용할 때 조건은 AND, OR등을 사용해 여러 조건을 조합할 수도 있다

각 테이블의 symbol 열과 date, last_crawel_date 열이라는 두 쌍의 열을 조건으로 사용한 쿼리 (이떄 조건으로 사용한 열값이 같은 데이터를 INNER JOIN해서 검색한다)

SELECT
a.symbol,
a.last_crawel_date,
b.date
FROM nasdaq_company AS a
INNER JOIN stock AS b on a.symbol = b.symbol AND a.last_crawel_date = b.date
WHERE a.symbol = 'MSFT'

profile
이진 입니다

0개의 댓글

Powered by GraphCDN, the GraphQL CDN