SAMPLE1 테이블
col1 |
1 |
2 |
3 |
4 |
SAMPLE2 테이블
col1 |
1 |
3 |
5 |
7 |
SAMPLE3 테이블
col1 |
2 |
4 |
8 |
위처럼 테이블들이 있고
SELECT A.COL1, B.COL1, C.COL1
FROM SAMPLE1 A, SAMPLE2 B, SAMPLE3 C
WHERE
A.COL1 = B.COL1 (+)
AND
A.COL1 = C.COL1 (+);
이 쿼리가 Oralce (+)사용한 조인인데 실행하면
Left Outer Join이긴 하지만 저기 AND 조건이 있어서 A.COL1 = B.COL1 AND A.COL1 = C.COL1 (수정했습니다)
만족되는 것만 출력될줄았았더니 결과로
A.COL1 | B.COL1 | C.COL1 |
---|---|---|
1 | 1 | null |
3 | 3 | null |
2 | null | 2 |
4 | null | 4 |
이렇게 나오더라... 이러면 Left Outer Join에 의해 이렇게 출력된건 알았는데
AND조건은 엿바꿔 먹었누? A.COL1 = B.COL1이랑 A.COL1 = C.COL1가 만족되는것만 필터링되어서 출력되어야할 줄 알았는데
왜 저렇게 나온건지 모르겠넹... 누가좀 알려주세요!!!
GPT말로는 AND 조건이 참으로 평가되지 않더라도 LEFT OUTER JOIN떄문에 그렇다는데 그럼 AND는 뭐하러있는겨
아래는 MYSQL에서 ANSI표준으로 조인한겁니다
년째 고민중
A.COL1 = B.COL1 = C.COl1 이 나오려면 inner join 해야하지 않나??
오라클 잘모르긴 하지만 위에 쿼리를 바꾸면
SELECT A.COL1, B.COL1, C.COL1
FROM SAMPLE1 AS A
LEFT OUTER JOIN SAMPLE2 AS B
ON A.COL1 = B.COL1
LEFTOUTER JOIN SAMPLE3 AS C
ON A.COL1 = C.COL1
이렇게 실행되는거야?
그러면 첫번째 join a,b 의 결과로
A.COL1 | B.COL1
1 | 1
2 | null
3 | 3
4 | null
이렇게 임시 테이블 만들거고,
여기서 임시테이블이랑 C랑 A.COL1 = C.COL1 조건으로 2번째 left outer join하니까
A.COL1 | B.COL1 | C.COL1
1 | 1 | null
2 | null | 2
3 | 1 | null
4 | null | 4
이렇게 되는거 아녀?
파멸라이더
급하게 적느라 잘못 적었어요 A.COL1 = B.COL1 AND A.COL1 = C.COL1입니당 죄송해여..
쿼리문 적으신것과 똑같이 실행되는게 맞습니다 적으신것도 실행하면 제가 적은 결과랑 똑같이나와여
북북노인
원했던 결과를 적어봐
파멸라이더
원했던건 A.COL1 = B.COL1 AND A.COL1 = C.COL1조건이 필터링되어서 나올 줄 알았어요
문제에 나온 쿼리라서 해보는데 AND가 들어간 이유와 역할을 모르겠습다..
ANSI JOIN 문법으로는
FROM SAMPLE1 A
LEFT OUTER JOIN SAMPLE2 B ON A.COL1 = B.COL1
LEFT OUTER JOIN SAMPLE3 C ON A.COL1 = C.COL1;
인데 여기는 AND가 없어서 똑같은 결과지만 이해가 잘되는데 ORACLE문법은 JOIN에다가 AND쓰고 있어서요..
북북노인
방금 써준 left outer join 을 간단하게 쓸 수 있게 해주는게 오라클의 (+) 문법이라…
둘이 결과가 같은거임
파멸라이더
ANSI 표준은 AND로 연결할 필요 없는데 오라클에서는 AND로 조인을 연결해주길래 이해가 잘안가고
조인에 AND연산자는 두 조건이 참이여야하는데 두 조인이 다 참이라는게 뭔말인지 이해가 안가네요
애플파인애플
SELECT A.COL1, B.COL1, C.COL1
FROM SAMPLE1 A, SAMPLE2 B, SAMPLE3 C
WHERE
A.COL1 = B.COL1 (+)
AND
B.COL1 = C.COL1 (+);
마지막줄 잘 보고 바꿔서 해봐
질문이 이상해서 원하던 결과인지는 모르겠지만
파멸라이더
저게 문제라서 마지막 A.COL1 = C.COL1 (+)를 전제로 하고 나오더라구여
애플파인애플
조인 AND 조건을 잘못 이해하는것 같은데, inner join에서는 말한대로 A=B=C 일치되는것만 출력될거야.
근데 outer join은 기준이 되는 A는 무조건 다 나오게 하라는 뜻이야.
outer join에서 AND 는 상대가 되는 B,C의 제약조건으로만 작동한다고 생각하면 될듯?
파멸라이더
네 잘이해못합니다ㅠ
AND가 A.COL1 값이 B.COL1과 일치하고 동시에 A.COL1 값이 C.COL1과 일치해야 결과로 나오는걸로 아는데
left join이라 또 맨왼쪽은 다 출력되어야하고.. B, C의 제약조건이라는게 뭔지 잘 모르겠습니다
천연기념물323호
다들 헛소리만 하고 있으니깐 답을 알려주자면
SQL 표준은 ANSI고 오라클 (+) 문법은 쓰기 편할 뿐이지
ANSI와 완벽하게 매핑되는 멀쩡한 문법이 아님
그래서 니가 헷갈려하는 것처럼 중의적으로 보이는거고
오라클 독자규격이기 때문에 오라클에서 결과를 뱉는대로 시맨틱을 이해해야 함
천연기념물323호
FROM A
LEFT JOIN B ON A.col1 = B.col1
LEFT JOIN C ON A.col1 = C.col1
결과가 나오는대로 ANSI SQL을 써보면 이건데
니가 AND로 묶여야 되지 않음? 하고 있는건 그냥 나열일 뿐이고
실은 서로 다른 두 JOIN의 조건문이기 때문에 AND가 아닌 것임
파멸라이더
아 그럼 ANSI처럼 이해를 하는게 아니였다구요??
그러면 (+)문법에서 조인끼리 AND로 연결해주는거에서 AND는
제가 아는 두조건이 참이여야하는 AND와 같은 의미로 쓰이는게 아닌건가요? 그냥 2개의 left join의 연결역할만?
천연기념물323호
ㅇㅇ 이 경우에 그 AND는 AND가 아니고 그냥 조건절 목록인 것이다
내부 동작을 더 풀어서 얘기해주면 오라클식 Outer Join 조건은 파서에서부터 따로 관리하고
저기에 AND로 일반 필터랑 같이 써놔도 적용되는 시점이 아예 다름
지금 오라클 클라이언트 붙들고 있는거면 플랜 찍어서 보셈
B(+) / C(+) 이렇게 마크한 거가 얘는 B랑 OJ할 떄, 쟤는 C랑 OJ할 때 써주세요란 뜻임
파멸라이더
와 4시간동안 대가리 굴리면서 이해를 해봐도 안돼서 지피티가 자꾸 개소리해서 2시간 날려먹고 2시간 구글링하다가
여기 질문한건데 대갈빡 망치로 존나쎄게 맞은거같네요 정말 감사합니다 이런거 알 수 있는 방법이나 문서같은게 있을까요?
알아보려해도 찾을곳을 못찾겠어여 책을 사야하는건가
천연기념물323호
쿼리 플랜보는 법만 알면 자습하기 쉬워짐
오라클 로컬에서 돌리고 있는거면 아래 글 따라해보셈
https://spidyweb.tistory.com/460
파멸라이더
감사합니다 제 시간을 아껴주셨네요 오라클은 아직 안깔아서 머리로만 왜 그런지 생각중이라 시간날때 해보겠습니다
정리하면
저 오라클 쿼리의 아우터조인 연결해주는 AND가 오라클 독자규격이기때문에 두조건이 모두 참이여야하는 AND연산자로는 작동안하는거고
제가 질문한 오라클 쿼리는
LEFT JOIN B ON A.col1 = B.col1
LEFT JOIN C ON A.col1 = C.col1
위의 ANSI left 조인 문법처럼 똑같이
첫번째 조인수행후 두번째조인을 수행하며
조인마다 독립적인 조인을 수행하는데 쿼리문법상 2개의 조인을 나열해야하니
결과적으로는
A.COL1 = B.COL1 (+)
AND
A.COL1 = C.COL1 (+);
이렇게 두개의 조인 사이에 AND가 들어가게 되고 이 뜻은
A.COL1 = B.COL1 과
A.COL1 = C.COL1를 동시만족하는것만 조인하는뜻이 아니라
ANSI처럼 조인 마다 순서대로 각각 수행하는데
AND는 다른목적은 없고 두개의 조인을 문법상 나열하기위한 목적으로 사용되었다.
이렇게 이해를 해봤습니다
제가 이해를 잘못한 부분이 있나요?
천연기념물323호
파멸라이더
왐마 감사합니다잉 이젠 혼자서 더 열심히 공부해보겠습니다 행복하세용
천연기념물323호
오라클에서 이따위 문법을 쓰는 이유는
실제로 optimizer가 돌아갈 땐 니가 적은 쿼리가 뭐건 간에
연속된 JOIN을 오라클 문법처럼 한데 모아놓고
어떤 순서로 굴리는게 좋을지 짱구를 굴려보기 때문임
어차피 뭉칠거면 쿼리 쓸 때부터 대충 뭉개서 주고 알아서 돌림 되잖아?
라는 순수한 선의이자 악의에서 탄생한게 오라클 문법임
오라클 독자 문법을 썼을 때 플랜이 어떻게 떨어져서 뭘로 실행 되겠구나
라는 내부 동작에 대한 이해가 없으면 ANSI SQL만 사용하는게 맞음
느린 쿼리는 튜닝하면 되지만 의미가 다른 쿼리는 구제할 길이 없기 때문에