MySQL에서 전체 외부 가입을 수행하는 방법은 무엇입니까?


654

MySQL에서 완전 외부 조인을하고 싶습니다. 이것이 가능한가? MySQL은 Full Outer Join을 지원합니까?



4
이 질문은 더 나은 해답을 가지고
훌리오 마린

여기에 대한 답변에주의하십시오. SQL 표준에 따르면 전체 조인은 행에 대한 내부 조인이 null로 확장 된 일치하지 않는 모든 왼쪽 테이블 행을 null로 확장하여 모든 오른쪽 테이블 행을 통합합니다. 여기에있는 대부분의 답변은 잘못되었습니다 (주석 참조). 정확하지 않은 답변은 일반적인 경우를 처리하지 않습니다. 많은 (정의되지 않은) 공감대가 있지만. (내 답변 참조)
philipxy

기본이 아닌 키 / 그룹화 된 열로 조인하려고하면 어떻습니까? "state", "sells"주당 판매량 쿼리와 "state", "state"주당 지출 비용이있는 것처럼 두 쿼리 모두 group by ( "state")를 사용합니다. 두 쿼리 사이의 왼쪽 및 오른쪽 조인 사이의 합집합을 수행하면 판매가 있지만 비용이없는 몇 행, 비용이 있지만 판매가없는 몇 가지 행이 표시됩니다.이 시점까지 모든 것이 있습니다. 판매 및 지출과 반복 된 "주"열 ... 문제는 많지 않지만 옳지 않다 ...
Jairo Lozano

1
@JairoLozano 제약 조건은 쿼리 할 필요가 없습니다. 제약 조건이 추가 쿼리를 보유하면 그렇지 않은 원하는 답변을 반환합니다. 제약 조건은 주어진 인수에 대한 반환에 대한 전체 조인에 영향을 미치지 않습니다. 설명하는 문제는 작성한 쿼리가 잘못된 쿼리라는 것입니다. (아마도 사람들이 각각 다른 키를 포함하는 일부 조인을 원할 때 발생하는 일반적인 오류, 각각은 조인 및 / 또는 집계를 포함 할 수 있지만 모든 집계를 수행 한 다음 모든 집계 또는 이전 집계에 대해 집계하려고 잘못 시도합니다. .)
philipxy

답변:


669

MySQL에는 FULL JOIN이 없지만 에뮬레이션 할 수 있습니다 .

이 SO 질문 에서 코드 샘플을 작성 하면 다음이 있습니다.

두 개의 테이블 t1, t2로 :

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

위 쿼리는 FULL OUTER JOIN 연산이 중복 행을 생성하지 않는 특수한 경우에 작동합니다. 위 쿼리는 UNIONset 연산자에 따라 쿼리 패턴에 의해 도입 된 중복 행을 제거합니다. 두 번째 쿼리에 반 조인 패턴을 사용하여 중복 행이 도입되는 것을 피한 다음 UNION ALL 집합 연산자를 사용하여 두 집합을 결합 할 수 있습니다. FULL OUTER JOIN이 중복 행을 리턴하는보다 일반적인 경우에는 다음을 수행 할 수 있습니다.

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.id IS NULL

33
실제로 당신이 쓴 것은 정확하지 않습니다. UNION을 수행 할 때 중복을 제거하고 때로는 두 개의 다른 테이블을 결합 할 때 중복이 있어야하기 때문입니다.
Pavle Lekic

158
이것은 올바른 예입니다.(SELECT ... FROM tbl1 LEFT JOIN tbl2 ...) UNION ALL (SELECT ... FROM tbl1 RIGHT JOIN tbl2 ... WHERE tbl1.col IS NULL)
Pavle Lekic

8
차이점은 제가 UNION ALL
Pavle Lekic

5
그리고 나는 당신이 스스로 그렇게 말하고 있음을 알았습니다. 이 오류가 발생하고 UNION ALL이 항상 더 효율적일 경우를 대비하여 답변을 업데이트 할 수 있습니까?
ysth

10
@ypercube : t1and에 중복 행이 없으면 t2이 답변의 쿼리는 FULL OUTER JOIN을 에뮬레이트하는 결과 집합을 반환합니다. 그러나 더 일반적인 경우, 예를 들어 SELECT 목록에 반환 된 행을 고유하게 만들기에 충분한 열 / 표현이 포함되어 있지 않으면이 쿼리 패턴 으로는 에서 생성 된 집합을 재현하기에 충분하지 않습니다FULL OUTER JOIN . 보다 충실한 에뮬레이션을 얻으려면 UNION ALLset 연산자가 필요하고 쿼리 중 하나에 안티 조인 패턴 이 필요합니다 . Pavle Lekic (위) 의 주석은 올바른 쿼리 패턴을 제공합니다 .
spencer7593

351

Pablo Santa Cruz 가 한 대답 은 정확합니다. 그러나 누군가이 페이지를 우연히 발견하고 더 자세한 설명을 원할 경우 여기에 자세한 설명이 있습니다.

테이블 예

다음 테이블이 있다고 가정하십시오.

-- t1
id  name
1   Tim
2   Marta

-- t2
id  name
1   Tim
3   Katarina

내부 조인

내부 조인은 다음과 같습니다.

SELECT *
FROM `t1`
INNER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

다음과 같이 두 테이블에 모두 나타나는 레코드 만 가져 오십시오.

1 Tim  1 Tim

내부 조인은 명시 적으로 양방향이기 때문에 방향이 없습니다 (왼쪽 또는 오른쪽). 양쪽에 일치해야합니다.

외부 조인

반면 외부 조인은 다른 테이블에서 일치하지 않는 레코드를 찾기위한 것입니다. 따라서, 조인의 어느 쪽 이 누락 된 레코드를 가질 수 있는지 지정해야합니다.

LEFT JOINRIGHT JOIN에 대한 나타내는 표현이된다 LEFT OUTER JOINRIGHT OUTER JOIN; 아래의 전체 이름을 사용하여 외부 조인과 내부 조인의 개념을 강화합니다.

왼쪽 외부 조인

왼쪽 외부 조인은 다음과 같습니다.

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

... 다음과 같이 오른쪽 테이블에서 일치하는지 여부에 관계없이 왼쪽 테이블에서 모든 레코드를 가져옵니다.

1 Tim   1    Tim
2 Marta NULL NULL

오른쪽 외부 조인

다음과 같은 오른쪽 외부 조인

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

... 왼쪽 테이블과 일치하는지 여부에 관계없이 오른쪽 테이블에서 모든 레코드를 가져올 수 있습니다.

1    Tim   1  Tim
NULL NULL  3  Katarina

완전 외부 조인

완전 외부 조인은 다른 테이블과 일치하는지 여부에 관계없이 두 테이블의 모든 레코드를 제공하며 일치하지 않는 양쪽에 NULL이 있습니다. 결과는 다음과 같습니다.

1    Tim   1    Tim
2    Marta NULL NULL
NULL NULL  3    Katarina

그러나 Pablo Santa Cruz가 지적했듯이 MySQL은 이것을 지원하지 않습니다. 다음과 같이 왼쪽 조인과 오른쪽 조인의 UNION을 수행하여 에뮬레이션 할 수 있습니다.

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`;

UNION"이 두 쿼리를 모두 실행 한 다음 결과를 서로 쌓아 올리십시오"라는 의미로 생각할 수 있습니다 . 일부 행은 첫 번째 쿼리에서 나오고 일부는 두 번째 쿼리에서 나옵니다.

UNIONMySQL에서 a 는 정확한 중복을 제거합니다. Tim은 두 쿼리 모두에 표시되지만 결과 UNION는 그를 한 번만 나열합니다. 저의 데이터베이스 전문가는이 동작에 의존해서는 안된다고 생각합니다. 따라서 더 명확하게 WHERE하기 위해 두 번째 쿼리에 절을 추가 할 수 있습니다 .

SELECT *
FROM `t1`
LEFT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`

UNION

SELECT *
FROM `t1`
RIGHT OUTER JOIN `t2` ON `t1`.`id` = `t2`.`id`
WHERE `t1`.`id` IS NULL;

당신이 다른 한편, 만약 싶어 어떤 이유로 중복을보고, 당신은 사용할 수 있습니다 UNION ALL.


4
MySQL의 경우 겹치지 않으면 UNION ALL 대신 UNION을 사용하지 않는 것이 좋습니다 (위의 Pavle 주석 참조). 귀하의 답변에 그 효과에 더 많은 정보를 추가 할 수 있다면,이 질문에 대한 대답이 더 철저하기 때문에 선호되는 답변이라고 생각합니다.
Garen

2
"데이터베이스 전문가 동료"의 추천이 맞습니다. 관계형 모델 (Ted Codd 및 Chris Date가 수행 한 모든 이론적 작업) 측면에서 마지막 양식의 쿼리는 두 개의 다른 세트를 결합하기 때문에 FULL OUTER JOIN을 에뮬레이트합니다. 두 번째 쿼리는 "중복"을 도입하지 않습니다 ( 에서 생성되지 않은 행은 이미 첫 번째 쿼리에 의해 반환되었습니다 FULL OUTER JOIN. 그런 식으로 쿼리를 수행하고 UNION을 사용하여 중복을 제거하는 데 아무런 문제가 없습니다. 그러나 실제로를 복제 FULL OUTER JOIN하려면 안티 조인 쿼리 중 하나가 필요합니다.
spencer7593 2016 년

1
@IstiaqueAhmed : 목표는 FULL OUTER JOIN 작업을 에뮬레이트하는 것입니다. 두 번째 쿼리에는 해당 조건이 필요하므로 일치하지 않는 행 (조인 방지 패턴) 만 반환됩니다. 해당 조건이 없으면 쿼리는 외부 조인입니다. 일치하는 행과 일치하지 않는 행을 반환합니다. 일치하는 행은 이미 첫 번째 쿼리에서 반환되었습니다. 두 번째 쿼리가 동일한 행을 (다시) 반환하면 행이 복제되어 결과가 FULL OUTER JOIN과 같지 않습니다 .
spencer7593

1
@IstiaqueAhmed : UNION작업이 중복을 제거 한다는 것은 사실입니다 . 그러나 FULL OUTER JOIN에 의해 ​​리턴되는 중복 행을 포함하여 모든 중복 행을 제거합니다. 에뮬레이션하려면 a FULL JOIN b올바른 패턴이 (a LEFT JOIN b) UNION ALL (b ANTI JOIN a)있습니다.
spencer7593

1
훌륭한 설명과 함께 매우 간결한 답변. 고마워
Najeeb

35

union쿼리를 사용하면 중복이 full outer join제거되며 중복을 제거하지 않는 동작과 다릅니다 .

[Table: t1]                            [Table: t2]
value                                  value
-------                                -------
1                                      1
2                                      2
4                                      2
4                                      5

이것은 다음의 예상 결과입니다 full outer join.

value | value
------+-------
1     | 1
2     | 2
2     | 2
Null  | 5
4     | Null
4     | Null

이는 사용의 결과 leftright Joinunion:

value | value
------+-------
Null  | 5 
1     | 1
2     | 2
4     | Null

[SQL Fiddle]

내 제안 쿼리는 다음과 같습니다

select 
    t1.value, t2.value
from t1 
left outer join t2  
  on t1.value = t2.value
union all      -- Using `union all` instead of `union`
select 
    t1.value, t2.value
from t2 
left outer join t1 
  on t1.value = t2.value
where 
    t1.value IS NULL 

예상 결과와 동일한 위 쿼리 결과 :

value | value
------+-------
1     | 1
2     | 2
2     | 2
4     | NULL
4     | NULL
NULL  | 5

[SQL Fiddle]


@Steve Chambers : [의견에서 감사합니다!]
참고 : 이는 효율성과 같은 결과를 생성하는 데 가장 적합한 솔루션 일 수 있습니다 FULL OUTER JOIN. 이 블로그 게시물 은 또한 방법 2에서 인용 한 내용을 잘 설명합니다. "이것은 중복 행을 올바르게 처리하고 행하지 말아야 할 것은 포함하지 않습니다. UNION ALL평범한 대신 사용해야 UNION하므로 유지하려는 중복을 제거합니다. 중복을 정렬하거나 제거 할 필요가 없으므로 큰 결과 집합에서 훨씬 더 효율적일 수 있습니다. "


full outer join시각화 및 수학 에서 제공되는 다른 솔루션을 추가하기로 결정 했지만 위의 방법이 아니라 더 읽기 쉽습니다.

완전 외부 조인은 (t1 ∪ t2)모두 포함 t1또는 포함 t2
(t1 ∪ t2) = (t1 ∩ t2) + t1_only + t2_only: 모두 포함 되지 않은 모두 t1t2포함 t1되지 않은 t2모든 t2것을 의미합니다 t1.

-- (t1 ∩ t2): all in both t1 and t2
select t1.value, t2.value
from t1 join t2 on t1.value = t2.value    
union all  -- And plus 
-- all in t1 that not exists in t2
select t1.value, null
from t1
where not exists( select 1 from t2 where t2.value = t1.value)    
union all  -- and plus
-- all in t2 that not exists in t1
select null, t2.value
from t2
where not exists( select 1 from t1 where t2.value = t1.value)

[SQL Fiddle]


우리는 동일한 작업 견인 시간을하고 있습니다 .t1 및 t2에 대한 하위 쿼리가 있으면 mysql은 동일한 작업을 더 많이 수행해야합니까? 우리는이 상황에서이 사용 별칭을 제거 할 수 :
카비의 Hossain

임시 테이블을 사용하는 것이 좋습니다.).
shA.t

5
이 방법은 효율성과 같은 결과를 생성하는 데 가장 적합한 솔루션 인 것 같습니다 FULL OUTER JOIN. 이 블로그 게시물 은 또한 방법 2에서 인용하는 방법을 잘 설명합니다. "이것은 중복 행을 올바르게 처리하고 행하지 말아야 할 것은 포함하지 않습니다. 일반 UNION 대신 UNION ALL을 사용해야합니다. 중복을 정렬하거나 제거 할 필요가 없기 때문에 대규모 결과 집합에서 훨씬 더 효율적일 수 있습니다. "
Steve Chambers

2
@SteveChambers 너무 늦었지만 의견을 주셔서 감사합니다. 귀하의 의견을 추가 한 다음 더 강조하기 위해 답변을 드리겠습니다. 동의하지 않으면 의견을 롤백하십시오.).
shA.t

문제 없음 @ shA.t-IMO 이것은 실제로 더 많은 투표를해야하며 / 또는 허용되는 답변이어야합니다.
Steve Chambers

6

MySql에는 FULL-OUTER-JOIN 구문이 없습니다. 다음과 같이 LEFT JOIN과 RIGHT JOIN을 모두 수행하여 에뮬레이션해야합니다.

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id  
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

그러나 MySql에는 RIGHT JOIN 구문이 없습니다. MySql의 외부 조인 단순화 에 따르면 오른쪽 조인은 쿼리 의 FROMand ON절에서 t1과 t2를 전환하여 동등한 왼쪽 조인으로 변환 됩니다. 따라서 MySql Query Optimizer는 원래 쿼리를 다음과 같이 변환합니다.

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id  
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id

이제 같이 원래 쿼리를 작성에 전혀 해를 끼치 지 당신이있는 WHERE 절과 같은 조건이있는 경우 말하지만, 없다 에 가입하기 전에 - 온 조건 또는 AND 조건 ONA는 절을, 가입시 - 술어 다음, 당신을 악마를보고 싶을 수도 있습니다. 자세한 내용입니다.

MySql 쿼리 옵티마이 저는 술어가 널 거부 인지 여부를 정기적으로 점검합니다 . Null-Rejected 정의 및 예 이제 RIGHT JOIN을 수행했지만 t1의 열에 WHERE 술어가 있으면 널 거부 시나리오 가 발생할 위험이 있습니다.

예를 들어, 다음 쿼리는-

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'

Query Optimizer가 다음으로 번역됩니다.

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.col1 = 'someValue'
UNION
SELECT * FROM t2
LEFT JOIN t1 ON t2.id = t1.id
WHERE t1.col1 = 'someValue'

따라서 테이블 순서가 변경되었지만 술어는 여전히 t1에 적용되지만 t1은 이제 'ON'절에 있습니다. t1.col1이 NOT NULL 열로 정의되면 이 쿼리는 널이 거부 됩니다.

null 거부 된 모든 외부 조인 (왼쪽, 오른쪽, 전체)은 MySql에 의해 내부 조인으로 변환됩니다.

따라서 예상 한 결과는 MySql이 반환하는 결과와 완전히 다를 수 있습니다. MySql의 RIGHT JOIN에 버그가 있다고 생각할 수도 있지만 그렇지 않습니다. MySql 쿼리 최적화 프로그램이 작동하는 방식입니다. 따라서 담당자는 쿼리를 구성 할 때 이러한 뉘앙스에주의를 기울여야합니다.


4

SQLite에서는 다음을 수행해야합니다.

SELECT * 
FROM leftTable lt 
LEFT JOIN rightTable rt ON lt.id = rt.lrid 
UNION
SELECT lt.*, rl.*  -- To match column set
FROM rightTable rt 
LEFT JOIN  leftTable lt ON lt.id = rt.lrid

우리는 그것을 사용할 수 있습니까? 다음과 같이 : SELECT * FROM leftTable lt LEFT JOIN rightTable rt ON lt.id = rt.lrid UNION SELECT lt. *, rl. *-열 세트와 일치하려면 leftTable lt RIGHT JOIN rightTable rt ON lt.id = rt.lrid ;
Kabir Hossain

예, 그러나 SQLite는 올바른 조인을 지원하지 않지만 MYSQL에서는 예
Rami Jamleh

4

위의 답변 중 어느 것도 중복 된 값이있을 때 의미를 따르지 않기 때문에 실제로 올바른 것은 없습니다.

(이 복제본 에서와 같은) 쿼리의 경우 :

SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.Name = t2.Name;

올바른 내용은 다음과 같습니다.

SELECT t1.*, t2.*
FROM (SELECT name FROM t1 UNION  -- This is intentionally UNION to remove duplicates
      SELECT name FROM t2
     ) n LEFT JOIN
     t1
     ON t1.name = n.name LEFT JOIN
     t2
     ON t2.name = n.name;

NULL값 으로 작업해야하는 경우 (필요할 수도 있음) 대신 NULL-safe 비교 연산자 를 사용하십시오 .<=>=


3
이것은 종종 좋은 솔루션이지만 열이 null 일 FULL OUTER JOIN때마다 다른 결과를 제공 할 수 있습니다 name. union all안티 조인 패턴 이있는 쿼리는 외부 조인 동작을 올바르게 재현해야하지만, 더 적합한 솔루션은 컨텍스트와 테이블에서 활성화 된 제약 조건에 따라 다릅니다.
fthiella

@fthiella. . . 좋은 지적입니다. 나는 대답을 조정했다.
Gordon Linoff

1
괜찮습니다. 그러나 null 안전 비교 연산자는 조인을 성공시킵니다. t1과 t2 모두에 null 이름이있는 경우 전체 외부 조인 동작과
다릅니다

@fthiella. . . 이 작업을 수행하는 가장 좋은 방법에 대해 생각해야합니다. 그러나 받아 들여진 대답이 얼마나 잘못되었는지에 따라 거의 모든 것이 정답에 더 가깝습니다. (양쪽에 여러 개의 키가 있으면 답이 틀립니다.)
Gordon Linoff

1
예, 일반적인 해결책으로 받아 들여진 대답이 잘못되었습니다.을 사용하는 것이 맞다고 생각 union all하지만, 그 대답은 기존 복제본을 유지하지만 새로운 복제본을 추가하지 못하게하는 첫 번째 쿼리 또는 두 번째 쿼리에서 안티 조인 패턴을 누락합니다. 상황에 따라이 솔루션과 같은 다른 솔루션이 더 적합 할 수 있습니다.
fthiella

3

명확성을 위해 shA.t의 쿼리를 수정했습니다.

-- t1 left join t2
SELECT t1.value, t2.value
FROM t1 LEFT JOIN t2 ON t1.value = t2.value   

    UNION ALL -- include duplicates

-- t1 right exclude join t2 (records found only in t2)
SELECT t1.value, t2.value
FROM t1 RIGHT JOIN t2 ON t1.value = t2.value
WHERE t2.value IS NULL 

3

다음을 수행 할 수 있습니다.

(SELECT 
    *
FROM
    table1 t1
        LEFT JOIN
    table2 t2 ON t1.id = t2.id
WHERE
    t2.id IS NULL)
UNION ALL
 (SELECT 
    *
FROM
    table1 t1
        RIGHT JOIN
    table2 t2 ON t1.id = t2.id
WHERE
    t1.id IS NULL);

1

교차 결합 솔루션 에 대해 무엇을 말했 습니까?

SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2 
ON 1=1;

2
아니요, 이것은 교차 조인입니다. t1의 모든 행을 t2의 모든 행과 일치 select (select count(*) from t1) * (select count(*) from t2))시켜 결과 집합의 행 과 함께 가능한 모든 조합 세트를 생성합니다 .
Marc L.

이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법이유 에 대한 추가 컨텍스트를 제공 하면 답변의 장기적인 가치가 향상됩니다.
Alexander

어떤 추가가 도움이 될 수 있습니까? 어쩌면 예?
Super Mario

0
SELECT
    a.name,
    b.title
FROM
    author AS a
LEFT JOIN
    book AS b
    ON a.id = b.author_id
UNION
SELECT
    a.name,
    b.title
FROM
    author AS a
RIGHT JOIN
    book AS b
    ON a.id = b.author_id

0

또한 가능하지만 select에서 동일한 필드 이름을 언급해야합니다.

SELECT t1.name, t2.name FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT t1.name, t2.name FROM t2
LEFT JOIN t1 ON t1.id = t2.id

이것은 왼쪽 조인의 결과를 복제하는 것입니다.
Matthew 읽기

-1

응답을 수정하고 모든 행을 포함합니다 (Pavele Lekic의 응답을 기반으로 함)

    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    WHERE b.`key` is null
    )
    UNION ALL
    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    where  a.`key` = b.`key`
    )
    UNION ALL
    (
    SELECT b.* FROM tablea a
    right JOIN tableb b ON b.`key` = a.key
    WHERE a.`key` is null
    );

아니요, 이것은 "외부 전용"조인 유형으로 tablea, 일치하지 않는 행만 반환 tableb하고 그 반대도 마찬가지입니다. 당신이하려고 UNION ALL,하는 것이 두 테이블이 동등하게 보장되지 않으므로 열을 주문한 경우에만 작동합니다.
Marc L.

그것은 작동합니다, 나는 임시 데이터베이스 tablea (1,2,3,4,5,6) 및 tableb (4,5,6,7,8,9)에 행에 3 열 "id", "number"가 있으며 "name_number"를 텍스트로 사용하면 결과적으로 (1,2,3,7,8,9) 만 있습니다.
Rubén Ruíz

1
그것은 외부 조인이 아닙니다. 외부 조인에는 일치하는 멤버도 포함됩니다.
Marc L.

새로운 문장은 모든 결과 1,2, ..., 9
를가집니다

-2

대답:

SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id;

다음과 같이 다시 만들 수 있습니다.

 SELECT t1.*, t2.* 
 FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp
 LEFT JOIN t1 ON t1.id = tmp.id
 LEFT JOIN t2 ON t2.id = tmp.id;

UNION 또는 UNION ALL 답변을 사용하면 기본 테이블에 중복 항목이있는 경우에 적용되지 않습니다.

설명:

UNION 또는 UNION ALL이 커버 할 수없는 경우가 있습니다. FULL OUTER JOIN을 지원하지 않으므로 mysql에서 이것을 테스트 할 수 없지만이를 지원하는 데이터베이스에서는이를 설명 할 수 있습니다.

 WITH cte_t1 AS
 (
       SELECT 1 AS id1
       UNION ALL SELECT 2
       UNION ALL SELECT 5
       UNION ALL SELECT 6
       UNION ALL SELECT 6
 ),
cte_t2 AS
(
      SELECT 3 AS id2
      UNION ALL SELECT 4
      UNION ALL SELECT 5
      UNION ALL SELECT 6
      UNION ALL SELECT 6
)
SELECT  *  FROM  cte_t1 t1 FULL OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2;

This gives us this answer:

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

UNION 솔루션 :

SELECT  * FROM  cte_t1 t1 LEFT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2
UNION    
SELECT  * FROM cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

잘못된 답변을 제공합니다.

 id1  id2
NULL  3
NULL  4
1  NULL
2  NULL
5  5
6  6

UNION ALL 솔루션 :

SELECT  * FROM cte_t1 t1 LEFT OUTER join cte_t2 t2 ON t1.id1 = t2.id2
UNION ALL
SELECT  * FROM  cte_t1 t1 RIGHT OUTER JOIN cte_t2 t2 ON t1.id1 = t2.id2

또한 올바르지 않습니다.

id1  id2
1  NULL
2  NULL
5  5
6  6
6  6
6  6
6  6
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

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

SELECT t1.*, t2.*
FROM (SELECT * FROM t1 UNION SELECT name FROM t2) tmp 
LEFT JOIN t1 ON t1.id = tmp.id 
LEFT JOIN t2 ON t2.id = tmp.id;

다음을 제공합니다.

id1  id2
1  NULL
2  NULL
NULL  3
NULL  4
5  5
6  6
6  6
6  6
6  6

순서는 다르지만 정답과 일치합니다.


귀엽지 만 UNION ALL해결책이 잘못되었습니다 . 또한 UNION필요한 중복 제거로 인해 큰 소스 테이블에서 속도가 느려지 는 솔루션을 제공합니다 . 마지막으로 필드 id가 subquery에 없기 때문에 컴파일 되지 않습니다 tmp.
Marc L.

나는 속도에 대해 결코 주장하지 않았으며, OP도 속도에 대해 언급하지 않았다. UNION ALL (어느 쪽을 지정하지 않습니까?)을 가정하고 둘 다 정답을 제공합니다. 더 빠르다는 주장을하고 싶다면 벤치 마크를 제공해야하며 OP에서 벗어날 것입니다. 질문.
Angelos

하위 쿼리에없는 ID에 대한 관찰에 관해서는 오타를 수정했습니다. 지적 해 주셔서 감사합니다. 귀하의 허위 진술은 모호합니다. 더 많은 정보를 제공 할 수 있다면이를 해결할 수 있습니다. 귀여움에 대한 최종 관찰에 대해서는 아무런 언급이 없으며 SQL의 논리에 중점을 둡니다.
Angelos

3
오해 : " UNION ALL해결 방법 : ...도 올바르지 않습니다." 제시 한 코드 where t1.id1 is null는에서 제공해야하는 오른쪽 조인 ( ) 에서 교차 제외를 제외 합니다 UNION ALL. 다시 말해, 귀하의 솔루션은 다른 솔루션 중 하나가 잘못 구현 된 경우에만 다른 모든 솔루션보다 우선합니다. "귀여움"에 대한 포인트. 정말 사과했습니다.
Marc L.

-3

표준 SQL 말한다 full join on입니다 inner join onunion all널 (null) 확장 타의 추종을 불허하는 왼쪽 테이블 행은 union all우측 테이블 행이 널 (null)로 연장했다. 즉 inner join onunion all을 입력 left join on하지만 inner join on union all행을 입력 right join on하지는 않습니다 inner join on.

left join onunion all right join on이에 없습니다 inner join on. 당신이 알고있는 경우 또는 inner join on결과가 "다음 특정 권리 테이블 컬럼에 널 (null)을 가질 수 right join on없는 행을 inner join on"의 행입니다 right join onon연장 조건 and이 열은 is null.

즉, 마찬가지로 right join on union all적절한 left join on행입니다.

에서 "내부 조인"과 "외부 조인"의 차이점은 무엇입니까? :

(SQL Standard 2006 SQL / Foundation 7.7 구문 규칙 1, 일반 규칙 1 b, 3 c & d, 5 b)

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