반응형
(INNER)JOIN에 따른 ON/WHERE 절 제약 조건
ON절은 WHERE절보다 순서 상 실행 속도가 더 빠르다.
FROM → ON → JOIN → WHERE
INNER JOIN을 사용하는 경우, ON이든 WHERE든 어디에 조건을 주든 상관이 없다. 즉, 아래의 세 쿼리는 서은ㅇ에 약간의 차이는 있을 수 있지만 결과물에 차이를 보이지는 않는다.
-- 첫 번째 쿼리
SELECT D.deptno, D.dname, E.ename, E.sal
FROM dept D, emp E
WHERE D.deptno = E.deptno AND E.sal > 2000;
-- 두 번째 쿼리
SELECT D.deptno, D.dname, E.ename, E.sal
FROM dept D
INNER JOIN emp E
ON D.deptno = E.deptno
WHERE E.sal > 2000;
-- 세 번째 쿼리
SELECT D.deptno, D.dname, E.ename, E.sal
FROM dept D
INNER JOIN emp E
ON D.deptno = E.deptno AND E.sal > 2000;
INNER JOIN은 존재하는 값에 대해서만 출력하기 때문에, 조건의 위치나 테이블의 순서와 무관하게 같은 실행 계획을 통해 같은 값이 출력된다.
그러나, LEFT/RIGHT JOIN 등 OUTER JOIN을 사용하게 되면 조건의 순서와 위치가 매우 중요해진다.
OUTER JOIN(LEFT, RIGHT)시 ON/WHERE 절 제약 조건
LEFT JOIN 시,
우측(NULL 값으로 채워지는 쪽)의 추가 제약 조건은 반드시 ON절에 넣어야 하고
좌측의 추가 제약 조건은 WHERE절에 넣어야 한다.
아래 쿼리는 정확한 쿼리와, 주로 실수하는 쿼리의 예시이다.
/* 첫 번째 쿼리 (원하는 결과값) */
SELECT D.deptno, SUM(E.sal)
FROM dept D
LEFT JOIN emp E
ON D.deptno = E.deptno AND E.sal > 2000 -- 우측 테이블 제약 조건
WHERE D.loc = 'CHICAGO' -- 좌측 테이블 제약 조건
GROUP BY D.deptno
ORDER BY D.deptno;
/* 두 번째 쿼리 (잘못된 쿼리)
좌/우 테이블의 제약 조건이 둘 다 WHERE절에 위치
deptno로 조인하고 where절에서 2000 이 초과되는 직원을 필터링 하게 되어
sal > 2000 인 40번 부서가 없는 결과가 출력됨 */
SELECT D.deptno, SUM(E.sal)
FROM dept D
LEFT JOIN emp E
ON D.deptno = E.deptno
WHERE E.sal > 2000 AND D.loc = 'CHICAGO' -- 좌/우 제약조건 모두 WHERE절
GROUP BY D.deptno
ORDER BY D.deptno;
/* 세 번째 쿼리 (잘못된 쿼리)
좌/우 제약조건의 위치가 바뀌어있음
INNER JOIN의 결과가 출력됨 */
SELECT D.deptno, SUM(E.sal)
FROM dept D
LEFT JOIN emp E
ON D.deptno = E.deptno AND D.loc = 'CHICAGO' -- 좌측 제약조건
WHERE E.sal > 2000 -- 우측 제약조건
GROUP BY D.deptno
ORDER BY D.deptno;
/* 네 번째 쿼리 (잘못된 쿼리)
좌/우 제약조건이 모두 ON절에 위치함 */
SELECT D.deptno, SUM(E.sal)
FROM dept D
LEFT JOIN emp E
ON D.deptno = E.deptno AND D.loc = 'CHICAGO' AND E.sal > 2000 -- 좌/우 제약조건 모두 ON절
GROUP BY D.deptno
ORDER BY D.deptno;
LeetCode, Average Selling Price 문제
각 날짜에 맞는 가격을 부여해 제품 별, 평균 가격을 추출하라
SELECT u.product_id, ROUND(SUM(u.units*p.price)/SUM(u.units), 2) AS average_price
FROM prices p
LEFT JOIN unitssold u
ON p.product_id = u.product_id AND u.purchase_date BETWEEN p.start_date AND p.end_date
GROUP BY 1
price 테이블을 기준으로 unitssold 테이블과 join을 하되 product_id가 서로 같도록 join을 한다.
이때 purchase_date가 start_date와 end_date 사이에 있는 조건을 추가해야하는데, 해당 조건은 unitssold 테이블에 적용되는 것이므로 LEFT JOIN 우측의 제약 조건이다. 따라서 ON에 해당 조건을 추가해주었다.
반응형