개발자 미니민의 개발스터디

[Oracle] 오라클 - 조인 (INNER JOIN 종류 / EQUI JOIN 등)

by mini_min
[Oracle]
오라클 - 조인 (INNER JOIN 종류 / EQUI JOIN 등)

✔️ 조인(joins)

: 둘 이상의 테이블, 뷰의 행을 결합하는 쿼리다.

: 쿼리의 FROM 절에 여러 테이블이 나타날 때마다 조인을 수행한다.

: 선택 목록은 이러한 테이블에서 컬럼을 선택할 수 있다.

: 조인된 두 테이블에서 하나의 공통된 컬럼 이름이 있으면, 모호성 피하기 위해 테이블 이름을 정확하게 명시해야한다.

❌ 명확하게 테이블 이름 명시하지 않으면 모호한 컬럼 이름이라고 실행안됨

 

❤️ 조인 조건

: FROM 또는 WHERE 절에 조인 조건이 포함된다.

 

 

 

✔️ INNER JOIN

: 조건에 만족하는 행만 반환하며, 둘 이상의 테이블을 조인한다.

 

ex) 테이블 

         -- 분류 테이블(분류코드, 분류명, 상위분류코드)
            SELECT bcCode, bcSubject, pcCode FROM bclass;

         -- 출판사 테이블(출판사번호, 출판사명, 전화번호)
            SELECT pNum, pName, pTel FROM pub;

         -- 책 테이블(서적코드, 서적명, 가격, 분류코드, 출판사번호)
            SELECT bCode, bName, bPrice, bcCode, pNum FROM book;

         -- 저자 테이블(저자번호, 서적코드, 저자명)
            SELECT aNum, bCode, aName FROM author;

         -- 고객 테이블(고객번호, 고객명, 전화번호)
            SELECT cNum, cName, cTel FROM cus;

         -- 회원 테이블(고객번호, 회원아이디, 회원패스워드, 이메일)
            SELECT cNum, userId, userPwd, userEmail FROM member;
    
         -- 판매 테이블(판매번호, 판매일자, 고객번호)
            SELECT sNum, sDate, cNum FROM sale;

         -- 판매 상세 테이블(판매상세번호, 판매번호, 서적코드, 판매수량)
            SELECT dNum, sNum, bCode, qty FROM dsale;

 

 

 

✔️ EQUI JOIN

: 조건에 정확하게! 일치하는 경우에만 조인한다.

기본적으로 조인은 테이블에 별명을 주는 것이 편하다.

'=' 을 통해 주는 조인!

 

-- 기본형식

SELECT [테이블명1.]컬럼명, [테이블명2.]컬럼명 ....
           FROM 테이블명1, 테이블명2
           WHERE 테이블명1.컬럼명 = 테이블명2.컬럼명  [AND 조건]
           

--2번째 형식
           SELECT [테이블명1.]컬럼명, [테이블명2.]컬럼명 ....
           FROM 테이블명1
           [ INNER ] JOIN 테이블명2 ON 테이블명1.컬럼명 = 테이블명2.컬럼명
💡 FROM 에 여러 테이블을 주는 것보다, 2번째 형식처럼 기준되는 테이블 하나를 FROM 에 두고 나머지는 (INNER) JOIN 으로 사용하는게 좋다. 

❌ USING 사용하는 형식도 있는데, 별로 권하지 않는다고 함
SELECT b.bCode, bName, bPrice, b.pNum, pName, sDate, s.cNum, cName, qty, bPrice * qty
	FROM book b
	JOIN pub p ON b.pNum = p.pNum
	JOIN dsale d ON b.bCode = d.bCode
	JOIN sale s ON d.sNum = s.sNum
	JOIN cus c ON c.cNum = s.cNum;

 

 

 

🔒 문제

-- 고객명:서울서점의 판매현황

        -- BOOK / PUB / sale / cus   / dsale / (book 이랑 dsale)
	-- 책코드 , 책이름, 책가격, 출판사명, 판매일자, 고객번호, 고객이름, 수량, 금액(수량*단가)
SELECT b.bCode, b.bName, p.pName, s.sDate, c.cNum, c.cName, qty, (qty*bPrice) amt
FROM book b
JOIN pub p ON b.pNum = p.pNum
JOIN dsale d ON d.bCode = b.bCode 
JOIN sale s ON d.sNum = s.sNum
JOIN cus c ON s.cNum = c.cNum
WHERE cName = '서울서점';
💡 조인 한 뒤, WHERE 절로 조건 줄 수도 있음!
테이블 명 명시잘해야한다 ㅜㅜ
book 테이블을 가지고 연결... 연결해서 조인하기

 

 

-- 판매된 책코드(bCode), 책이름(bName), 판매권수합이 80권 이상

SELECT b.bCode, bName, SUM(qty) 판매수량합	
	FROM book b
	JOIN dsale d ON b.bCode = d.bCode
	GROUP BY b.bCode, bName
	HAVING SUM(*) >= 80
	ORDER BY bCode;

 

 

-- 판매된 책코드(bCode), 책이름(bName) : 중복배제

SELECT DISTINCT b.bCode, bName	
	FROM book b
	JOIN dsale d ON b.bCode = d.bCode
💡 DISTINCT 를 쓰거나 unique 를 사용해서 중복도 배제할 수 있다.

 

 

⭐-- (랭킹 함수 사용) 판매 권수 합이 가장 많이 판매된 책

SELECT bCode, bName FROM(
    SELECT b.bCode, bName, SUM(qty) 판매수량합, RANK()OVER(ORDER BY SUM(qty)DESC) 랭킹
	FROM book b
	JOIN dsale d ON b.bCode = d.bCode
	GROUP BY b.bCode, bName
	ORDER BY 판매수량합 DESC
    ) WHERE 랭킹 = 1;
💡 서브쿼리 안에서 랭킹을 구하고, 밖에 있는 SELECT 절에서 랭킹 구하기 가능!
만약, 1~5등 까지 출력하고 싶으면, IN 사용해서 답 구하기

 

 

 

🔒 문제 - 2

-- 올해의 판매 현황

  -- BOOK / PUB / sale / cus   / dsale / (book 이랑 dsale)
	-- 책코드 , 책이름, 책가격, 출판사명, 판매일자, 고객번호, 고객이름, 수량, 금액(수량*단가)
SELECT b.bCode, b.bName, p.pName, s.sDate, c.cNum, c.cName, qty, (qty*bPrice) amt
FROM book b
JOIN pub p ON b.pNum = p.pNum
JOIN dsale d ON d.bCode = b.bCode 
JOIN sale s ON d.sNum = s.sNum
JOIN cus c ON s.cNum = c.cNum
WHERE TO_CHAR(SYSDATE, 'YYYY') = TO_CHAR(sDate, 'YYYY');
💡 이번 달 판매 현황이 궁금하다면,
TO_CHAR(sDate, 'MM') 으로 비교하기!

작년 판매 현황이 궁금하다면,
WHERE TO_CHAR(SYSDATE - (INTERVAL '1' YEAR), 'YYYY') = TO_CHAR(sDate, 'YYYY');

 

 

-- 년도별 판매 현황

SELECT TO_CAHR(sDate, 'YYYY'), SUM(qty*bPrice)
	FROM book b
	JOIN dsale d ON b.bCode = d.bCode
	JOIN sale s ON d.sNum = s.sNum
	GROUP BY TO_CAHR(sDate, 'YYYY');

 

 

-- 지난 달 고객번호, 고객명, 판매금액 합 ⭐⭐ 인터벌 불가

SELECT c.cNum, c.cName, TO_CHAR(sDate, 'YYYY-MM') 년도, SUM(qty*bPrice) 판매금액합
FROM book b
JOIN dsale d ON b.bCode = d.bCode
JOIN sale s ON d.sNum = s.sNum
JOIN cus c ON c.cNum = s.cNum
WHERE TO_CHAR(sDate, 'YYYYMM') = TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'YYYYMM')
GROUP BY c.cNum, c.cName, TO_CHAR(sDate, 'YYYY-MM')
ORDER BY c.cNum, 년도;
💡MONTH 는 인터벌로 비교하면 예상치 못한 오류가 발생하는 경우가 많음.
그래서 MONTH 계산할 때는 ADD_MONTHS 또는 MONTHS_BETWEEN 같은 함수 사용하는게 좋음

 

 

 

✔️ NATURAL JOIN

: 중복을 없애고 한 번씩만 나오게 하는 조인이다.

(거의 조인할 일이 없다고 함!)

 

-- 기본형식

SELECT 컬럼명, 컬럼명 ....
    FROM 테이블명1
    NATURAL JOIN  테이블명2

 

 

 

✔️ CROSS JOIN

: 카디션 곱 (곱한 갯수만큼 결과가 나온다.)

(마찬가지로 거의 조인할 일이 없다고 한다.)

 

-- 예시

SELECT p.pNum, pName, bCode, bName
	FROM pub p
	CROSS JOIN book b;

 

 

 

 

 

 

 

블로그의 정보

개발자 미니민의 개발로그

mini_min

활동하기