같은 테이블에서 두 번 조인하는 가장 좋은 방법은 무엇입니까?


108

이것은 약간 복잡하지만 2 개의 테이블이 있습니다. 구조가 다음과 같다고 가정 해 봅시다.

*Table1*
ID
PhoneNumber1
PhoneNumber2

*Table2*
PhoneNumber
SomeOtherField

Table1.PhoneNumber1-> Table2.PhoneNumber 또는 Table1.PhoneNumber2-> Table2.PhoneNumber를 기준으로 테이블을 조인 할 수 있습니다.

이제 PhoneNumber1, PhoneNumber1에 해당하는 SomeOtherField, PhoneNumber2에 해당하는 SomeOtherField가 포함 된 결과 집합을 가져오고 싶습니다.

테이블을 두 번 조인하거나 ON 절에서 OR로 한 번 조인하는 두 가지 방법을 생각했습니다.

방법 1 :

SELECT t1.PhoneNumber1, t1.PhoneNumber2, 
   t2.SomeOtherFieldForPhone1, t3.someOtherFieldForPhone2
FROM Table1 t1
INNER JOIN Table2 t2
   ON t2.PhoneNumber = t1.PhoneNumber1
INNER JOIN Table2 t3
   ON t3.PhoneNumber = t1.PhoneNumber2

이것은 작동하는 것 같습니다.

방법 2 :

어떻게 든 다음과 같은 쿼리를 사용하려면-

SELECT ...
FROM Table1
INNER JOIN Table2 
   ON Table1.PhoneNumber1 = Table2.PhoneNumber OR
      Table1.PhoneNumber2 = Table2.PhoneNumber

나는 이것을 아직 작동시키지 않았고 그것을 할 방법이 있는지 확실하지 않습니다.

이를 수행하는 가장 좋은 방법은 무엇입니까? 어느 쪽도 간단하거나 직관적이지 않습니다 ...이 작업을 수행하는 더 간단한 방법이 있습니까? 이 요구 사항은 일반적으로 어떻게 구현됩니까?

답변:


151

먼저 전화 번호를 자연 키로 사용하지 않도록이 테이블을 리팩토링하려고합니다. 나는 자연 키의 팬이 아니며 이것이 좋은 예입니다. 자연 키, 특히 전화 번호와 같은 것은 자주 변경 될 수 있습니다. 변경 사항이 발생할 때 데이터베이스를 업데이트하는 것은 오류가 발생하기 쉬운 엄청난 골칫거리입니다. *

설명하는 방법 1 은 최선의 방법입니다. 이름 지정 체계와 짧은 별칭으로 인해 약간 간결 해 보이지만 동일한 테이블을 여러 번 조인하거나 하위 쿼리 등을 사용하는 경우 별칭은 친구입니다.

나는 조금만 정리할 것입니다.

SELECT t.PhoneNumber1, t.PhoneNumber2, 
   t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2
FROM Table1 t
JOIN Table2 t1 ON t1.PhoneNumber = t.PhoneNumber1
JOIN Table2 t2 ON t2.PhoneNumber = t.PhoneNumber2

제가 한:

  • INNER를 지정할 필요가 없습니다. LEFT 또는 RIGHT를 지정하지 않는다는 사실을 암시합니다.
  • 기본 조회 테이블에 n- 접미사를 붙이지 마십시오.
  • 명확하게하기 위해 여러 번 사용할 테이블 별칭을 N 접미사로 지정합니다.

* DBA가 자연 키 업데이트의 골칫거리를 피하는 한 가지 방법은 기본 키와 외래 키 제약 조건을 지정하지 않는 것입니다. 나는 실제로 이것을 자주 본 적이 없다.


이 솔루션을 내 문제에 사용했습니다. 많은 도움이되었습니다. 그러나 이것을보기 전에 서로 조인해야하는 테이블을 볼 수있는 곳에 기본 키와 외래 키를 적용했습니다. 이것이 왜 나쁜 생각입니까?
1 권

6
@volumeone-내 대답의 마지막 부분을 오해했을 수 있습니다. 기본 및 외래 키 좋은 생각입니다. 그것들을 피하는 것은 나쁜 습관, 나쁜 디자인, 그리고 아주 나쁜 것입니다.
Paul Sasik

완벽 해 .. 그런데 왜이 상황에서 별칭이 필수입니까?
Raiden Core

동일한 테이블을 두 번 조인하지 않고이를 수행 할 수있는 방법이 있습니까? 어쩌면 ... WHERE 절에 조건을 사용
JohnOsborne

5

첫 번째는 Phone1 또는 (가능성이 더 높은) phone2가 null 일 수없는 경우에 좋습니다. 이 경우 내부 조인 대신 Left 조인을 사용하려고합니다.

두 개의 전화 번호 필드가있는 테이블이있는 경우 일반적으로 잘못된 신호입니다. 일반적으로 이것은 데이터베이스 디자인에 결함이 있음을 의미합니다.


그레이트 포인트! 이것은 나중에 나에게 큰 두통을 일으켰을 것입니다 ... 감사합니다!
froadie 2010

4

UNION두 개의 조인을 결합 하는 데 사용할 수 있습니다 .

SELECT Table1.PhoneNumber1 as PhoneNumber, Table2.SomeOtherField as OtherField
  FROM Table1
  JOIN Table2
    ON Table1.PhoneNumber1 = Table2.PhoneNumber
 UNION
SELECT Table1.PhoneNumber2 as PhoneNumber, Table2.SomeOtherField as OtherField
  FROM Table1
  JOIN Table2
    ON Table1.PhoneNumber2 = Table2.PhoneNumber

1
나는 이것을 생각했지만 하나의 비정규 화 된 레코드로 반환되어야합니다 ...
froadie

오 그래, 나는 거의 그 반대라고 생각했다. 이 경우 첫 번째 방법과 같은 방법을 사용하여 수행합니다. 내 대답을 편집하겠습니다.
Pointy

3

내 문제는 전화 번호가 없거나 하나만 존재하더라도 기록표시하는 것이 었습니다 (전체 주소록). 따라서 오른쪽에 해당하는 항목이 없더라도 왼쪽에서 모든 레코드를 가져 오는 LEFT JOIN을 사용했습니다. 나를 위해 이것은 Microsoft Access SQL 에서 작동 합니다 (괄호가 필요합니다!)

SELECT t.PhoneNumber1, t.PhoneNumber2, t.PhoneNumber3
   t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2, t3.someOtherFieldForPhone3
FROM 
(
 (
  Table1 AS t LEFT JOIN Table2 AS t3 ON t.PhoneNumber3 = t3.PhoneNumber
 )
 LEFT JOIN Table2 AS t2 ON t.PhoneNumber2 = t2.PhoneNumber
)
LEFT JOIN Table2 AS t1 ON t.PhoneNumber1 = t1.PhoneNumber;

2

첫 번째 방법은 적절한 접근 방식이며 필요한 작업을 수행합니다. 그러나 내부 조인을 사용 Table1하면 두 전화 번호가 모두에있는 경우 에만 행을 선택 합니다 Table2. 의 LEFT JOIN모든 행 Table1이 선택 되도록 할 수 있습니다 . 전화 번호가 일치하지 않으면 SomeOtherFields는 null이됩니다. 일치하는 전화 번호가 하나 이상 있는지 확인하려면 다음을 수행하십시오.WHERE t2.PhoneNumber IS NOT NULL OR t3.PhoneNumber IS NOT NULL

두 번째 방법에는 문제가있을 수 있습니다. 및 ? Table2가 둘 다 있으면 어떻게됩니까 ? 어떤 행이 선택됩니까? 데이터, 외래 키 등에 따라 문제가 될 수도 있고 아닐 수도 있습니다.PhoneNumber1PhoneNumber2

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