복붙노트

[SQL] 왼쪽에 방지 중복 값 가입

SQL

왼쪽에 방지 중복 값 가입

내가 가입 왼쪽에서 중복 값을 가지고 상황에 직면했다. 나는 이것이 내가 원하는에서 원하는 동작하지만 달리있을 것 같아요.

사람, 부서 및 연락처 : 나는 세 개의 테이블이있다.

사람 :

id bigint,
person_name character varying(255)

학과 :

person_id bigint,
department_name character varying(255)

연락처 :

person_id bigint,
phone_number character varying(255)

SQL 쿼리 :

SELECT p.id, p.person_name, d.department_name, c.phone_number 
FROM person p
  LEFT JOIN department d 
    ON p.id = d.person_id
  LEFT JOIN contact c 
    ON p.id = c.person_id;

결과 :

id|person_name|department_name|phone_number
--+-----------+---------------+------------
1 |"John"     |"Finance"      |"023451"
1 |"John"     |"Finance"      |"99478"
1 |"John"     |"Finance"      |"67890"
1 |"John"     |"Marketing"    |"023451"
1 |"John"     |"Marketing"    |"99478"
1 |"John"     |"Marketing"    |"67890"
2 |"Barbara"  |"Finance"      |""
3 |"Michelle" |""             |"005634"

나는 그것이 수행 조인 선택된 행에 곱하는되어 유지 무엇을 알고있다. 그러나 그것은 그들이 단지 더 큰 데이터 세트로 문제를 확대 할 필요가 반복되는 값으로 사람 존 관련된 동안 023451,99478,67890 모두 부서위한 전화 번호와 같은 감각을 준다. 그래서, 여기에 내가 원하는 것입니다 :

id|person_name|department_name|phone_number
--+-----------+---------------+------------
1 |"John"     |"Finance"      |"023451"
1 |"John"     |"Marketing"    |"99478"
1 |"John"     |""             |"67890"
2 |"Barbara"  |"Finance"      |""
3 |"Michelle" |""             |"005634"

이것은 내 상황의 샘플 내가 테이블 및 쿼리의 큰 세트를 사용하고 있습니다. 그래서, 필요의 종류 일반적인 솔루션입니다.

해결법

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

    1.나는이 문제 "크로스 프록시로 참여"를 부르는 것을 좋아합니다. 어떠한 정보 (WHERE 또는 JOIN 조건) 테이블 부서 및 연락처가 일치 해야하는 방법이 없기 때문에, 그들은 십자가에 가입 프록시 테이블 사람을 통해 수 있습니다 - 당신에게 데카르트의 제품을 제공합니다. 이것과 매우 유사합니다 :

    나는이 문제 "크로스 프록시로 참여"를 부르는 것을 좋아합니다. 어떠한 정보 (WHERE 또는 JOIN 조건) 테이블 부서 및 연락처가 일치 해야하는 방법이 없기 때문에, 그들은 십자가에 가입 프록시 테이블 사람을 통해 수 있습니다 - 당신에게 데카르트의 제품을 제공합니다. 이것과 매우 유사합니다 :

    더 설명이.

    쿼리를위한 솔루션 :

    SELECT p.id, p.person_name, d.department_name, c.phone_number
    FROM   person p
    LEFT   JOIN (
       SELECT person_id, min(department_name) AS department_name
       FROM   department
       GROUP  BY person_id
       ) d ON d.person_id = p.id
    LEFT   JOIN (
       SELECT person_id, min(phone_number) AS phone_number
       FROM   contact
       GROUP  BY person_id
       ) c ON c.person_id = p.id;
    

    당신은 선택 할 부서 나 전화 번호를 정의하지 않았다, 그래서 나는 임의로 최소를 선택했다. 당신은 그것을 다른 방법으로 할 수 있습니다 ...

  2. ==============================

    2.나는 당신이 단지 특정 사람에 대한 부서의 목록과 전화를받을 필요가 있다고 생각합니다. 그러니 그냥 array_agg (또는 string_agg 또는 json_agg)를 사용합니다 :

    나는 당신이 단지 특정 사람에 대한 부서의 목록과 전화를받을 필요가 있다고 생각합니다. 그러니 그냥 array_agg (또는 string_agg 또는 json_agg)를 사용합니다 :

    SELECT
        p.id,
        p.person_name,
        array_agg(d.department_name) as "department_names",
        array_agg(c.phone_number) as "phone_numbers"
    FROM person AS p
    LEFT JOIN department AS d ON p.id = d.person_id
    LEFT JOIN contact AS c on p.id = c.person_id
    GROUP BY p.id, p.person_name
    
  3. ==============================

    3.테이블이 분명히 논의 단순화되어 있지만, 그들이 구조적으로 결함이 나타납니다. 테이블은 엔티티 및 / 또는 속성의 목록을 엔티티 사이의 관계를 보여보다는 단지로 구성되어야한다. 그리고 전화 번호는이 경우 (개인 또는 부서 엔티티의) 속성이라고 생각합니다.

    테이블이 분명히 논의 단순화되어 있지만, 그들이 구조적으로 결함이 나타납니다. 테이블은 엔티티 및 / 또는 속성의 목록을 엔티티 사이의 관계를 보여보다는 단지로 구성되어야한다. 그리고 전화 번호는이 경우 (개인 또는 부서 엔티티의) 속성이라고 생각합니다.

    첫 번째 단계는 관계 테이블을 작성하는 것, 기본 키 및 가능한 외래 키를 갖는 각. 이 예에서는 사람이 테이블 사용은 기본 키 person_id로해야하는 것이 도움이 될 것이며, 부서 테이블의 기본 키 department_id 사용. 일대 다 또는 다 대다 관계, 그에 따라 외래 키를 설정하기위한 다음보기 :

    한 사람을위한 테이블과 부서의 다른 테이블 : 요약하면, 만 시나리오에서 두 개의 테이블이 있어야합니다. 심지어 부서 테이블에 개인 전화 번호 (위격 테이블의 열) 및 부서 번호를 허용, 이것은 더 나은 방법이 될 것입니다.

    한 부서가 많은 번호 (또는 두 개 이상의 부서 주 단일 전화 번호)를 가질 때주의해야 할 점은, 그러나 이것은 원래의 질문의 범위를 넘어서는 것입니다.

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

    4.

    SELECT p.id, p.person_name, d.department_name, c.phone_number 
    FROM person p
      LEFT JOIN department d 
        ON p.id = d.person_id
      LEFT JOIN contact c 
        ON p.id = c.person_id 
    group by p.id, p.person_name, d.department_name, c.phone_number
    
  5. ==============================

    5.이러한 유형의 쿼리를 사용하여 SQL Server를 (당신은 당신이 그것을 원하는 각 열에 ID로 ORDER의 ID를 변경할 수 있습니다)

    이러한 유형의 쿼리를 사용하여 SQL Server를 (당신은 당신이 그것을 원하는 각 열에 ID로 ORDER의 ID를 변경할 수 있습니다)

    SELECT 
        p.id, 
        p.person_name, 
        d.department_name, 
        c.phone_number
    FROM
        person p
        LEFT JOIN 
        (SELECT *, ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY id) AS seq
         FROM department) d 
        ON d.person_id = p.id And d.seq = 1
        LEFT JOIN 
        ( SELECT *, ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY id) AS seq
         FROM contact) c 
        ON c.person_id = p.id And c.seq = 1;
    
  6. from https://stackoverflow.com/questions/30410622/prevent-duplicate-values-in-left-join by cc-by-sa and MIT license