과거 SQL 문법에서 FROM 절에 콤마(,) 를 사용한 조인방식을 사용하는 걸 볼 수 있는데,
의외로 명시적 조인 방식과 뭐가 다른지, 어떻게 동작하는지 잘 모르는 경우가 꽤 있습니다.
콤마를 이용한 조인은 어떻게 동작하며, 명시적조인과 어떻게 다른지
그리고, 어떤 방식을 사용하는 게 더 적절할지에 대해 알아보려고 합니다.
콤마 연산자 동작 방식
1.
WHERE 절이 없을 때:
•
CROSS JOIN 처럼 동작합니다.
•
두 테이블의 모든 행을 가능한 모든 조합으로 결합하여 카티션 곱을 수행합니다.
SELECT *
FROM table1, table2;
SQL
복사
이 경우 두 테이블의 모든 조합이 생성됩니다.
2.
WHERE 절이 있을 때:
•
조인 조건을 WHERE 절에 명시하게 되면, INNER JOIN과 동일하게 동작합니다.
•
즉, 두 테이블 간의 특정 조건에 맞는 행들만 결합됩니다.
SELECT *
FROM table1, table2
WHERE table1.id = table2.id;
SQL
복사
위 쿼리는 INNER JOIN과 동일하게 table1과 table2의 id가 일치하는 행들만 반환합니다.
결론
•
콤마 연산자(,)는 WHERE 절이 없으면 CROSS JOIN (카티션 곱)을 수행하고, WHERE 절이 있으면 INNER JOIN처럼 동작합니다.
어떤 조인 문법을 사용하는 게 적절할까 ?
어떤 방식이 옳고 그름을 나누기보단 DBMS 문서 및 개발자 리뷰를 취합해 봤을 때
명시적 조인 을 권장하고 있는 걸로 보입니다.
이에 대한 이유로 몇 가지를 나열해보겠습니다.
1. 가독성 및 명확성
•
명시적인 JOIN 구문은 의도가 명확하게 드러납니다. 어떤 종류의 조인(내부 조인, 외부 조인, 크로스 조인 등)을 수행하는지 명확히 알 수 있어 코드의 가독성이 높아집니다.
•
콤마 연산자를 사용하면 조인이 일어나는 부분이 불분명해지고, 특히 복잡한 쿼리에서 WHERE 절을 통한 조건식이 헷갈릴 수 있습니다.
예시) 어떤 JOIN 을 의도했는지 혼동될 수 있음
-- 명시적 INNER JOIN
SELECT *
FROM table1
INNER JOIN table2 ON table1.id = table2.id;
-- 콤마 연산자를 사용한 INNER(?) JOIN
SELECT *
FROM table1, table2
WHERE table1.id = table2.id;
SQL
복사
위와 같이 명시적 조인을 하는경우 사용자의 의도가 명확하지만,
콤마 연산자를 사용한 경우 해당 쿼리가 CROSS JOIN, INNER JOIN 중에 어떤걸 의도한건지
혼동될 수 있다. (물론, 위의 쿼리는 짧아서 알아볼 수 있지만, 복잡해질수록 알아보기 힘들다.)
2. 표준 SQL에서의 일관성 및 미래호환성
•
콤마 연산자는 옛날 스타일의 SQL 문법입니다. 최신 SQL 표준에서는 조인 구문을 명시적으로 쓰는 것이 일관성 있는 방식으로 권장됩니다.
•
SQL 표준이나 특정 DBMS에서 미래의 호환성 문제를 일으킬 가능성이 있습니다. 예를 들어, 일부 최신 SQL 기능이나 확장을 사용하려면 명시적인 JOIN을 사용하는 것이 필수적일 수 있습니다.
◦
예시 : 명시적 조인에서는 NATURAL JOIN 같은 고급 조인 기능을 사용할 수 있지만, 콤마 조인은 이러한 기능을 제공하지 않습니다.
•
협업시 명시적 조인을 주로 사용하는 개발자와 혼동이 있을 가능성도 배제할 수 없습니다.
최신 문법으로 처음 접한 개발자와 협업 시 문제가 될 소지가 있습니다.
3. 명시적 조인과 혼합 사용시 오류가능성 (MySQL 문서참고)
SELECT *
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id,
table3 t3
WHERE t3.some_column = t2.some_column;
SQL
복사
문제:
위 쿼리에서 table1과 table2는 INNER JOIN으로 조인하고, table2와 table3은 콤마(암시적 조인)로 연결되어 있습니다. 하지만 문제는, MySQL은 콤마 조인의 우선순위가 INNER JOIN보다 낮기 때문에, 다음과 같이 처리될 수 있습니다:
1.
먼저 콤마 조인인 table2와 table3의 카티션 곱(모든 행의 조합)이 먼저 생성됩니다.
2.
그 다음, 이 카티션 곱 결과에 대해 INNER JOIN이 적용됩니다.
이렇게 되면, table3.some_column = t2.some_column이라는 조건이 제대로 적용되지 않거나, Unknown column 오류가 발생할 수 있습니다.
MySQL 공식문서 : https://dev.mysql.com/doc/refman/8.4/en/join.html
INNER JOIN and , (comma) are semantically equivalent in the absence of a join condition: both produce a Cartesian product between the specified tables (that is, each and every row in the first table is joined to each and every row in the second table).
However, the precedence of the comma operator is less than that of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur. Information about dealing with this problem is given later in this section.
번역 :
INNER JOIN조인 조건이 없을 경우 및 , (쉼표)는 의미적으로 동일합니다. 둘 다 지정된 테이블 간의 카티전 곱을 생성합니다(즉, 첫 번째 테이블의 각 행은 두 번째 테이블의 각 행에 조인됩니다).
그러나 쉼표 연산자의 우선순위는 INNER JOIN, CROSS JOIN, LEFT JOIN, 등의 우선순위보다 낮습니다. 조인 조건이 있을 때 쉼표 조인을 다른 조인 유형과 혼합하면 다음과 같은 형태의 오류가 발생할 수 있습니다. 이 문제를 처리하는 방법에 대한 정보는 이 섹션의 뒷부분에서 제공됩니다. Unknown column 'col_name' in 'on clause'
4. LEFT JOIN 및 RIGHT JOIN 사용 불가
콤마 조인을 사용할 경우, OUTER JOIN (즉, LEFT JOIN 또는 RIGHT JOIN)과 같은 특수한 조인 방식을 사용할 수 없습니다. 아래와 같은 쿼리를 보세요:
SELECT *
FROM table1 t1, table2 t2
WHERE t1.id = t2.id;
SQL
복사
위 쿼리에서 LEFT JOIN을 사용하려고 하면 콤마 조인에서는 이를 구현할 방법이 없습니다. 반면, 명시적 조인 구문에서는 다음과 같이 쉽게 사용할 수 있습니다:
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id;
SQL
복사
이처럼, 콤마 조인으로는 OUTER JOIN 같은 복잡한 조인을 구현하기 어려워, 조인 조건이 다소 제한적입니다.
5. 성능 최적화에 불리
명시적 조인 구문을 사용할 때는 DBMS가 실행 계획을 최적화할 수 있는 여지가 더 큽니다.
반면, 콤마 조인을 사용하면 DBMS의 최적화가 제한적일 수 있어 성능 저하가 발생할 수 있습니다. 특히, 복잡한 조인일수록 명시적 구문을 사용하면 DBMS의 쿼리 최적화 엔진이 더 효율적으로 작동합니다.
예를들어 실행 계획에서 Full Table Scan(전체 테이블 스캔) 또는 Nested Loop Join(중첩 반복 조인)과 같은 비효율적인 접근 방식을 발견할 수 있습니다. 반면, 명시적 조인의 경우 Indexed Lookup(인덱스를 통한 조회) 또는 Hash Join(해시 조인) 등 더 효율적인 접근 방식이 나올 수 있습니다.
마치며
대부분은 프로그래밍 언어는 버전업을 통해 계속 발전하고, 이건 개발자들에게 편리함을 제공한다.
마찬가지로 SQL문법도 DBMS 가 발전함에 따라서 사용성 좋은 문법을 권장하게 되어 있습니다.
이 글에서 말하고자 하는 취지는 과거 문법이 잘못되었으니 고쳐써야 된다는 것이 절대 아니며,
효율적인 개발을 위한 현재 개발 트렌드를 알고서 적절한 문법을 사용하자는 것입니다.