안녕하세요. 현재 it개발 회사에 다니고 있는 사람입니다. 이번에 회사에서 서브쿼리에 대한 발표를 준비하던 중 의문점이 생겨서 질문을 올리게 되었습니다.
저는 조인이나 서브쿼리를 사용하는 이유가 다음에 있다고 생각하고 있습니다.
1.하나의 테이블에 모든 정보를 담을 수는 없다. 혹은 담을 수 있더라고 그 테이블에서 정보를 가져오는 것은 매우 어렵운 작업이 될 것이다.
2. 따라서 테이블은 그 테이블의 목적에 따라 적당한 수(약 10~20개 내외)의 컬럼 갯수를 지녀야 하며 컬럼은 테이블의 목적에 부합해야한다.
3. 1번의 이유로 하나의 테이블로 원하는 정보를 모두 보여줄 수 없을 때 테이블끼리의 조인이나, 서브쿼리를 이용해서 하나의 테이블 이상의 정보를 가져와야 하는 경우가 생긴 다.
현재 저는 서브쿼리나 조인이 위의 목적을 위해서 사용되어진다고 생각하고 있습니다. 따라서 저는 서브쿼리와 조인의 목적은 동일하며 다만, 목적을 이루는 과정이 다르기 때문에 서로 다른 이름으로 불리우고 있다고 추측하고 있는데 이 추측에 큰 무리가 없을까요? 또한 목적을 이루는 과정이 다르다면 둘이 어떤식으로 다른 지 궁금합니다. 또는, 제가 이해하고 있는 서브쿼리와 조인의 개념이 잘못된 점이 있다면 무엇이 있을지 궁금합니다. 이 쪽을 전공으로 배운것이 아니라 이러 기본적인 개념에서 의문점이 생기게 되어 질문드립니다.
1.서브쿼리나 조인을 사용하는 이유 : 테이블이 나누어져 있기 때문에 정보를 조합해야하기 때문이죠. 테이블을 왜 나누어야 하나? 하는 점은
정규화의 관점에서 바라보시면 좋습니다. 구글에서 정규화의 목적이라고 검색해보시면 테이블을 왜 나누어야 하는지에 대한 감이 오실 것이고요.
2.스칼라서브쿼리와 조인의 차이점 : 조인은 1:M의 관계로 데이터를 만들어줄 수 있지만 서브쿼리는 메인 테이블과 1:1의 관계여야 합니다.
스칼라서브쿼리에서 여러 결과를 리턴하면 쿼리 오류가 발생합니다. 또한 조인은 조인 대상 테이블에 여러 컬럼을 사용할 수 있지만
서브쿼리의 경우 하나의 컬럼 값만 가지고 올 수 있습니다.(혹은 여러컬럼을 concat하여 합친 형태로)
1:1 관계이라면 서브쿼리를 조인으로 바꿀 수도 있고 조인을 서브쿼리로 바꿀 수도 있습니다.
사용자가 바꾸지 않더라도 DBMS 자체적으로 서브쿼리를 조인형태로 바꾸고 쿼리를 실행하기도 합니다.
서브쿼리가 성능상 나을 때도 있고 조인이 성능상 나을 때도 있습니다.
조인의 경우 NL join, Hash join, Sort Merge join등 다양한 기법으로 데이터를 가져오게 됩니다만
스칼라서브쿼리의 경우 NL join과 매우 유사한 형태로 데이터를 가져옵니다.
메인 테이블 row 하나당 하나의 서브쿼리를 실행해서 데이터를 가져오는 방식입니다.
의문을 가지시고 공부하시는 점 매우 좋은 자세라 생각합니다^^
추가) 음.. 질문을 서브쿼리라고만 하셨는데 저는 정보를 가져온다는 관점에서 select절에 오는 스칼라서브쿼리에 대해서만 설명드렸네요ㅎㅎ
서브쿼리는 select절 뿐만 아니라 from절(인라인뷰), where절, order by 절등 다양한 위치에서 사용되기도 합니다. where 절 in형태로 사용한다면 1:M의 관계이더라도 오류가 발생하지 않습니다. 마찬가지로 in 절일 때 여러 컬럼을 가져올 수도 있고요.
ex) where (col1, col2) in (select col3, col4 from ~)
대부분의 서브쿼리는 메인 테이블과의 관계를 가지고 작성되지만 메인테이블과 관계없이 참조 값을 가져오기 위해 작성되기도 합니다.
ex) select (select sysdate from dual) today, col1, col2 from tab1
일반적으로 단순히 인라인뷰 형태로 작성한다고 하여 인라인뷰형태로 쿼리가 실행되지는 않습니다.
옵티마이저가 쿼리 수행전에 최적화하기 쉬운 형태로 쿼리를 변환하기 때문입니다.
select * from (select * from tab1 where col2 = 'A') a , (select * from tab2 where col2 = 'B') b where a.col1 = b.col1 -> 이러한 형태는 옵티마이저에 의해 아래와 같은 형태로 쿼리 변형될 확률이 큽니다. select * from tab1 a, tab2 b where a.col1 = bcol1 and a.col2 = 'A' and b.col2 = 'B'
개인적으로는 인라인뷰가 효용성이 있으려면 인라인뷰 형태 그대로 쿼리가 실행되는 형태일 때
효과가 있을 듯합니다.
group by 사용한 집계 쿼리, rownum을 활용하는 경우, union 연산, connect by 연산, 윈도우함수 사용 등
이러한 경우는 인라인뷰를 해체하지 않고 대부분 그대로 사용합니다.
혹은 쿼리의 가독성을 위해 인라인뷰를 사용하든지요.