LEFT OUTER JOIN은 왼쪽 테이블에있는 것보다 더 많은 레코드를 어떻게 반환 할 수 있습니까?


165

왼쪽 테이블의 모든 결과와 훨씬 큰 테이블의 추가 정보를 반환하는 매우 기본적인 LEFT OUTER JOIN이 있습니다. 왼쪽 테이블에는 4935 개의 레코드가 포함되어 있지만 외부 테이블에 추가하면 레코드 수가 훨씬 큽니다.

내가 아는 한 왼쪽 외부 조인은 왼쪽 테이블의 모든 레코드를 오른쪽 테이블의 일치하는 레코드와 일치시킬 수없는 행에 대해 null 값을 반환한다는 것은 절대적인 복음입니다. 왼쪽 테이블에있는 것보다 많은 행을 반환하는 것은 불가능하지만 모두 동일하게 발생합니다!

SQL 쿼리는 다음과 같습니다.

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

어쩌면 구문에서 실수를했거나 LEFT OUTER JOIN에 대한 나의 이해가 불완전합니다. 아마도 누군가 이것이 어떻게 발생할 수 있는지 설명 할 수 있기를 바랍니다.

추신

큰 답변에 감사드립니다. LEFT OUTER JOINS에 대한 이해가 훨씬 좋아졌습니다.하지만 왼쪽 테이블에 존재하는만큼의 레코드 만 반환하도록이 쿼리를 수정할 수있는 방법을 제안 할 수 있습니까?

이 쿼리는 순전히 보고서를 생성하기위한 것이며 중복 된 일치 항목은 문제를 혼동하기 만합니다.

/추신


5
"왼쪽 테이블에 존재하는만큼의 레코드를 리턴"하려면 일치 항목이 여러 개인 경우 오른쪽에서 어떤 행을 지정해야하는지 지정해야합니다.
AK

1
이것을 어떻게 지정합니까? 첫 번째 경기를 반환하고 싶습니다.
Simon Cross

1
첫 번째 일치의 의미를 정의해야합니다. 가장 빠른 기록, 가장 높은 ID를 가진 기록 또는 무엇을 원하십니까?
HLGEM

1
추가 테이블에서 기본 키와 일치하면 명령문이 정확합니다.
Prageeth godage

나는 종종 쿼리를 만들 때 이와 같은 리소스를 치트 시트로 사용 합니다. 링크가 끊어지면 google sql join 만 사용하십시오 . 그것들은 서로 다른 조인 유형의 벤 다이어그램입니다.
Zimano

답변:


190

LEFT OUTER JOIN은 가능한 경우 RIGHT 테이블과 조인 된 LEFT 테이블의 모든 레코드를 반환합니다.

일치하는 항목이 있으면 일치하는 모든 행을 계속 반환하므로 RIGHT의 두 행과 일치하는 LEFT의 한 행은 INNER JOIN과 같이 두 개의 ROWS로 반환됩니다.

편집 : 편집에 대한 응답으로 쿼리를 자세히 살펴 보았으므로 LEFT 테이블에서만 데이터를 반환하는 것처럼 보입니다. 따라서 LEFT 테이블의 데이터 만 원하고 LEFT 테이블의 각 행에 대해 하나의 행만 리턴하려는 경우 JOIN을 전혀 수행 할 필요가 없으며 LEFT 테이블에서 직접 SELECT를 수행 할 수 있습니다.


1
오른쪽 테이블에 참여하는 이유는 오른쪽 테이블에 적어도 하나의 레코드가있는 왼쪽에서만 레코드를 얻었지만 설명에 대해 대단히 감사합니다.
Jay Wilde

125
Table1                Table2
_______               _________
1                      2
2                      2
3                      5
4                      6

SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id

결과 :

1,null
2,2
2,2
3,null
4,null

1
아주 단순하면서도 강력합니다.
kiradotee

39

불가능하지 않습니다. 왼쪽 테이블의 레코드 수는 반환 할 최소 레코드 수입니다. 오른쪽 테이블에 왼쪽 테이블의 한 레코드와 일치하는 두 개의 레코드가 있으면 두 개의 레코드가 리턴됩니다.


12

포스트 스크립트에 대한 응답으로 원하는 것에 따라 다릅니다.

조인 조건에 대해 여러 개의 일치 항목이 있으므로 왼쪽 테이블의 각 행에 대해 여러 개의 행을 얻습니다. 쿼리의 왼쪽 부분에있는 총 결과와 동일한 수의 행을 가지려면 결합 조건이 일대일로 일치하는지 확인해야합니다.

또는 실제로 원하는 것에 따라 집계 함수를 사용할 수 있습니다 (예를 들어 오른쪽 부분에서 문자열을 원하면 왼쪽 행에 대한 오른쪽 결과의 쉼표로 구분 된 문자열 인 열을 생성 할 수 있습니다.

외부 조인에서 1 개 또는 2 개의 열만보고있는 경우 1 개의 결과가 보장되므로 스칼라 하위 쿼리 사용을 고려할 수 있습니다.


4
왼쪽 테이블에서 행만 반환하는 방법에 대한 제안을 제공했기 때문에 좋은 대답입니다.
karns

9

왼쪽 테이블의 각 레코드는 오른쪽 테이블에 일치하는 레코드가있는 횟수 (최소 1 개이지만 쉽게 1보다 클 수 있음)로 여러 번 반환됩니다.


8

INNER JOIN (정상 조인)과 마찬가지로 LEFT OUTER JOIN은 왼쪽 테이블의 각 행에 대해 오른쪽 테이블에서 찾은 수만큼 많은 결과를 반환합니다. 따라서 N x M까지 많은 결과를 얻을 수 있습니다. 여기서 N은 왼쪽 테이블의 행 수이고 M은 오른쪽 테이블의 행 수입니다.

LEFT OUTER JOIN에서 항상 N 이상의 최소 결과 수를 보장합니다.


1
나는 행 수가 N x M과 같을 때 생각하기 시작했고 내 마음에 오는 유일한 실제 상황은 N 또는 M이 1 일 때뿐입니다. 동의하십니까?
BartoszMiller

2
아뇨 조인 조건을 키 평등 조인으로 만 생각해서는 안됩니다. 날짜 범위, 부등식 등 임의 조건 일 수 있습니다. 두 가지 극단적 인 경우 : (a) N 개의 행이 M 개의 행 사이에서 단일 일치를 갖지 않은 경우 왼쪽 외부 조인은 N 개의 행을 NULL과 일치시킵니다. (b) 모든 N 행은 모든 M 행과 일치하며 결과는 N x M 행 세트입니다.
topchef

1
당신 말이 맞아요, 저는 키 평등의 관점에서만 조인을 생각하고있었습니다. "case b"의 예를 좋아합니다. "N 행마다 모든 M 행과 일치"는 N x M 행이 반환 될 때의 일반적인 레시피라고 생각합니다. 이는 키 평등에 대해서만 생각하면 시각화 할 수 없습니다.
BartoszMiller


6

왼쪽 외부 조인을 포함하는 쿼리의 "오른쪽"테이블에 where 절이있는 경우주의하십시오. 오른쪽에 where 절을 만족시키는 레코드가없는 경우 '왼쪽의 해당 레코드 '테이블이 쿼리 결과에 나타나지 않습니다 ....


1
그런 다음 해당 LEFT OUTER JOIN의 ON 절에 조건을 추가해야합니다.
Mik

6

오른쪽에서 하나의 행만 필요한 경우

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

아니면 그냥

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)

1
DDL과 DML을 제공하지 않았으므로 테스트하지 않았습니다. 어쨌든 나는 존재가 당신이 원하는 것이라고 생각합니다. 이것을 시도하십시오 : SELECT SuspReason, SiteID FROM (SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER () OVER (PARTITION BY SUSP.Susp_Visits.SiteID ORDER BY SUSP.Susp_Visits.SiteID) FROM. 가입 DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum) AS t WHERE RN = 1
AK

2

SUSP.Susp_Visits 행당 DATA.Dim_Member 테이블에 여러 행이있는 것처럼 보입니다.


2

Dim_Member의 여러 (x) 행이 Susp_Visits의 단일 행과 연관된 경우 resul 세트에 x 개의 행이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.