복붙노트

[SQL] 어떻게 FULL OUTER MySQL의에 가입 할까?

SQL

어떻게 FULL OUTER MySQL의에 가입 할까?

나는 완전 외부의 MySQL에 가입하고 싶어. 이게 가능해? 전체 외부는 MySQL이 지원 가입되어 있습니까?

해결법

  1. ==============================

    1.당신은 FULL은 MySQL을 JOINS 필요는 없지만, 확실히를 에뮬레이션 할 수 있습니다.

    당신은 FULL은 MySQL을 JOINS 필요는 없지만, 확실히를 에뮬레이션 할 수 있습니다.

    코드 샘플이 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
    

    완전 외부 중복 행을 생성하지 것이다 작업을 가입 특별한 경우를 작품 위의 쿼리. 쿼리는 위의 쿼리 패턴에 의해 도입 중복 행을 제거하는 UNION 집합 연산자에 따라 달라집니다. 우리는 두 번째 쿼리에 대한 패턴을 방지 조인을 사용하여 중복 행을 도입하지 않도록 다음 두 가지를 결합하는 UNION ALL 집합 연산자를 사용할 수 있습니다. 완전 외부 중복 행을 반환 가입보다 일반적인 경우에, 우리는이 작업을 수행 할 수 있습니다

    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
    
  2. ==============================

    2.파블로 산타 크루즈가 준 대답은 정확; 그러나, 경우에 사람이 페이지에서 발견 더 설명을하고자, 여기에 관한 자세한 세부 사항입니다.

    파블로 산타 크루즈가 준 대답은 정확; 그러나, 경우에 사람이 페이지에서 발견 더 설명을하고자, 여기에 관한 자세한 세부 사항입니다.

    우리는 다음과 같은 테이블이 있다고 가정 해 봅시다 :

    -- 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
    

    내부는 명시 적으로 양방향이기 때문에 (왼쪽 또는 오른쪽처럼) 방향이없는 조인 - 우리는 양쪽에 일치를 필요로합니다.

    외부 조인, 다른 한편으로는, 다른 테이블에서 일치가 없을 수 기록을 찾아 내기위한 것입니다. 따라서, 당신은 누락 된 기록을 가질 수 조인의 어느 쪽 지정해야합니다.

    왼쪽은 가입 및 오른쪽은 왼쪽 외부 조인과 오른쪽 외부 조인에 대한 속기 있습니다 가입; 외부 내부 조인 대 조인의 개념을 강화하기 위해 아래 나는 그들의 전체 이름을 사용합니다.

    A는 외부과 같이 가입 왼쪽 :

    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
    

    파블로 산타 크루즈 지적하지만, 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 생각할 수 있습니다; 행 중 일부는 첫 번째 쿼리와 두 번째의 일부에서 올 것이다.

    팀이 여기에 쿼리에 모두 표시,하지만 한 번 UNION의 결과는리스트 그를 : MySQL의에서 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을 사용할 수 있습니다.

  3. ==============================

    3.통합 쿼리를 사용하여 중복을 제거하고이 완전 외부의 동작은 중복 제거 결코 가입보다 다른 것입니다 :

    통합 쿼리를 사용하여 중복을 제거하고이 완전 외부의 동작은 중복 제거 결코 가입보다 다른 것입니다 :

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

    이 조인 완전 외부의 예상 된 결과입니다 :

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

    이 왼쪽 사용한 결과이며, 바로 노동 조합에 가입 :

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

    [SQL 바이올린]

    내 추천 검색어는 다음과 같습니다

    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 바이올린]

    내가 시각화 및 수학에 가입 완전 외부에서 오는 다른 솔루션을 추가하기로 결정, 그것은 좋은 것은 아닙니다 위와 같지만 더 읽기가 :

    -- (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 바이올린]

  4. ==============================

    4.MySQL은 구문을 FULL-외부-가입이 없습니다. 당신은 JOIN 모두 LEFT를 수행하여 에뮬레이션해야하고 RIGHT follows-로 가입하기

    MySQL은 구문을 FULL-외부-가입이 없습니다. 당신은 JOIN 모두 LEFT를 수행하여 에뮬레이션해야하고 RIGHT follows-로 가입하기

    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의 외측의 가입 간소화에 따르면, 오른쪽은 왼쪽 등가 변환 조인 쿼리로부터 ON 절에서 T1 및 T2를 전환하여 가입. 따라서, MySQL의 쿼리 최적화는 다음에 원래의 쿼리를 변환 -

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

    지금, 당신은 가입시 - 술어 ON 절에 조인하기 전에-조건 또는 AND 조건입니다 WHERE 절, 같은 조건이있는 경우 다음 말씀이 있으므로 원래 쿼리를 작성에 전혀 해가 없지만, 당신은 악마를 살펴 할 수 있습니다; 이는 세부 사항에 있습니다.

    MySQL의 쿼리 최적화가 널 거부하는 경우 정기적으로 조건을 확인합니다. 당신이 할 경우 이제, RIGHT,하지만 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'
    

    쿼리 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로 정의 된 경우 열은,이 쿼리는 널 거부됩니다.

    상관은 외부 조인 (왼쪽, 오른쪽, 전체) 즉 널 거부 변환된다 MySQL이 내부 조인.

    따라서 당신이 예상 할 수있는 결과는 MySQL이 반환하는 것과 전혀 다를 수 있습니다. 당신은 MySQL을의 권리와 자사의 버그가 가입 생각하지만, 그게 전부하지 못했습니다 수 있습니다. 그 얼마나 MySQL의 쿼리 최적화 작동합니다. 개발자-의 충전 그가 쿼리를 작성하는 경우 이러한 미묘한 차이에주의를 지불해야 그래서.

  5. ==============================

    5.SQLite는 당신은이 작업을 수행해야합니다 :

    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
    
  6. ==============================

    6.중복 된 값이있는 경우가 의미를 따르지 않기 때문에 위의 답변 중 어느 것도 실제로 정확하지 않습니다.

    중복 된 값이있는 경우가 의미를 따르지 않기 때문에 위의 답변 중 어느 것도 실제로 정확하지 않습니다.

    등 (이 중복에서)와 같은 쿼리 :

    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 안전 비교 연산자, <=> 아니라 = 이상을 사용합니다.

  7. ==============================

    7.더 명확하게하기 위해 shA.t의 쿼리를 수정 :

    더 명확하게하기 위해 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 
    
  8. ==============================

    8.다음과 같은 작업을 수행 할 수 있습니다 :

    다음과 같은 작업을 수행 할 수 있습니다 :

    (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);
    
  9. ==============================

    9.당신이 솔루션을 가입 크로스에 대해 뭐라고 뭐라고?

    당신이 솔루션을 가입 크로스에 대해 뭐라고 뭐라고?

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

    10.

    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
    
  11. ==============================

    11.또한 가능하지만, 당신은 선택의 동일한 필드 이름을 언급해야한다.

    또한 가능하지만, 당신은 선택의 동일한 필드 이름을 언급해야한다.

    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
    
  12. ==============================

    12.나는 응답을 수정하고, 작품의 모든 행을 포함 (Pavle Lekic의 응답 기준)

    나는 응답을 수정하고, 작품의 모든 행을 포함 (Pavle 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
        );
    
  13. ==============================

    13.대답:

    대답:

    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 ALL 응답을 사용하면 기본 테이블이 중복 된 항목이 가장자리의 경우 적용되지 않습니다.

    설명:

    노동 조합 또는 UNION ALL 커버 할 수없는 가장자리 경우가 있습니다. 이 FULL OUTER 조인을 지원하지 않기 때문에 우리는 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
    

    노조 솔루션 :

    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
    

    순서는 다르지만, 그렇지 않으면 정답과 일치합니다.

  14. ==============================

    14.전체에 가입 말합니다 표준 SQL 내부 행 조합에 널 (null) 조합 널 (null)에 의해 확장 모든 권리 테이블 행에 의해 확장 된 모든 타의 추종을 불허하는 왼쪽 테이블 행을 조인. 즉 내부 행 조합 왼쪽에있는 모든 행에 합류하지만 내부는 노동 조합에 오른쪽 가입의 모든 행에 합류하지만 내부하지가 가입에 가입 할 수 있습니다.

    전체에 가입 말합니다 표준 SQL 내부 행 조합에 널 (null) 조합 널 (null)에 의해 확장 모든 권리 테이블 행에 의해 확장 된 모든 타의 추종을 불허하는 왼쪽 테이블 행을 조인. 즉 내부 행 조합 왼쪽에있는 모든 행에 합류하지만 내부는 노동 조합에 오른쪽 가입의 모든 행에 합류하지만 내부하지가 가입에 가입 할 수 있습니다.

    즉 모든 오른쪽에 조인 행에 가입하지 내부의 행 조합에 가입 떠났다. 당신은 당신의 내면 다음 특정 권리 테이블 컬럼에 널 (null)을 가질 수 없습니다 결과에 가입 알고있는 경우 또는 "오른쪽 행에없는 내부가 조인에 참여"바로 확장 상태에와에 조인 행은 그 열은 null입니다.

    즉 유사 권리 행에 가입 노동 조합에 모든 적절한 왼쪽을 가입 할 수 있습니다.

    의 차이 무엇입니까에서와 "외부 조인", "내부 조인"?

  15. from https://stackoverflow.com/questions/4796872/how-to-do-a-full-outer-join-in-mysql by cc-by-sa and MIT license