FROM 라인의 SQL 왼쪽 조인 대 여러 테이블?


256

대부분의 SQL 방언은 다음 쿼리를 모두 허용합니다.

SELECT a.foo, b.foo
FROM a, b
WHERE a.x = b.x

SELECT a.foo, b.foo
FROM a
LEFT JOIN b ON a.x = b.x

이제 외부 조인이 필요할 때 두 번째 구문이 필요합니다. 그러나 내부 조인을 수행 할 때 첫 번째 구문보다 두 번째 구문을 선호해야하는 이유는 무엇입니까?


1
구파 : 어떻게 찾았어요? 내 질문은 "어떻게 할"보다 가장 좋은 방법이지만
jmucchiello

모범 사례이므로 이것을 Wiki로 만드십시오.
Binoj Antony

1
나는이 두 가지의 성과에 대해 언급 한 사람이 없다고 생각합니다. 누구든지 중요한 차이점에 대해 합리적인 것을 확인하거나 인용 할 수 있습니까?
ahnbizcad

@ahnbizcad 주어진 두 쿼리는 같은 일을하지 않습니다. 첫 번째는 INNER JOIN ON과 동일을 반환합니다. 구현은 DBMS 버전에 따라 다르지만 보장이 거의 없습니다. 그러나 쉼표 대 INNER JOIN ON / WHERE vs CROSS JOIN WHERE의 경우와 동등한 DBMS 변환은 쉽지 않습니다. 관계형 데이터베이스 쿼리 최적화 / 구현에 대해 배웁니다.
philipxy

자원 추천이 있습니까? 거대하고 조밀 한 매뉴얼이 여기서 배우려고하는 이유입니다.
ahnbizcad 2016 년

답변:


319

테이블을 나열 WHERE하고 조인 기준을 지정하기 위해 절을 사용하는 이전 구문 은 대부분의 최신 데이터베이스에서 더 이상 사용되지 않습니다.

그것은 단지 표시를위한 것이 아니며, 동일한 쿼리에서 INNER 및 OUTER 조인을 모두 사용할 때 이전 구문은 모호 할 수 있습니다.

예를 들어 보겠습니다.

시스템에 3 개의 테이블이 있다고 가정 해 봅시다.

Company
Department
Employee

각 테이블에는 서로 연결된 수많은 행이 있습니다. 여러 회사가 있고 각 회사에 여러 부서가있을 수 있으며 각 부서에 여러 직원이있을 수 있습니다.

이제 다음을 수행하려고합니다.

모든 회사를 나열하고 모든 부서와 모든 직원을 포함하십시오. 일부 회사에는 아직 부서가 없지만이를 포함시켜야합니다. 직원이있는 부서 만 검색하고 항상 모든 회사를 나열하십시오.

그래서 당신은 이것을합니다 :

SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
  AND Department.ID = Employee.DepartmentID

마지막 부서는 사람들과 부서 만 원하는 기준을 충족하기 위해 내부 조인이 있습니다.

자 이제 어떻게 되나요? 문제는 데이터베이스 엔진, 쿼리 최적화 프로그램, 인덱스 및 테이블 통계에 따라 다릅니다. 설명하겠습니다.

쿼리 옵티마이 저가이를 수행하는 방법이 먼저 회사를 고용하고 부서를 찾은 다음 직원과의 내부 참여를하는 것이라고 판단하면 부서가없는 회사는 얻지 못합니다.

그 이유는이 WHERE절이 행의 개별 부분이 아닌 최종 결과로 끝나는 행을 결정하기 때문입니다 .

이 경우 왼쪽 조인으로 인해 Department.ID 열이 NULL이므로 INNER JOIN to Employee의 경우 Employee 행에 대한 제약 조건을 충족시킬 방법이 없으므로 열이 없습니다. 나타나다.

반면에 쿼리 최적화 프로그램이 부서 직원 조인을 먼저 해결하기로 결정한 다음 회사와의 왼쪽 조인을 수행하면 해당 팀이 표시됩니다.

따라서 오래된 구문은 모호합니다. 쿼리 힌트를 처리하지 않고 원하는 것을 지정할 수있는 방법이 없으며 일부 데이터베이스에는 전혀 방법이 없습니다.

선택할 수있는 새 구문을 입력하십시오.

예를 들어 문제 설명에 명시된대로 모든 회사를 원할 경우 다음과 같이 작성하십시오.

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID

여기에서 부서 직원 조인을 하나의 조인으로 수행 한 다음 그 결과를 회사에 남겨 두도록 지정합니다.

또한 이름에 문자 X가 포함 된 부서 만 원한다고 가정 해 봅시다. 이전 스타일의 조인을 사용하면 이름에 X가있는 부서가 없지만 새로운 구문을 사용하면 회사를 잃을 위험이 있습니다.

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'

이 추가 절은 조인에 사용되지만 전체 행에 대한 필터는 아닙니다. 따라서 행에 회사 정보가 표시 될 수 있지만 해당 회사의 이름에 X가있는 부서가 없기 때문에 해당 행의 모든 ​​부서 및 직원 열에 NULL이있을 수 있습니다. 이전 구문으로는 어렵습니다.

그렇기 때문에 Microsoft는 다른 공급 업체 중에서 이전 외부 조인 구문을 더 이상 사용하지 않지만 SQL Server 2005 이후로는 이전 내부 조인 구문을 더 이상 사용하지 않습니다. 이전 스타일의 외부 조인 구문을 사용하여 Microsoft SQL Server 2005 또는 2008에서 실행되는 데이터베이스와 대화하는 유일한 방법은 해당 데이터베이스를 8.0 호환 모드 (일명 SQL Server 2000)로 설정하는 것입니다.

또한, WHERE 절을 사용하여 쿼리 최적화 프로그램에서 테이블을 여러 개 던지면서 기존 방식은 "여기에서 최선을 다하십시오"라고 말하는 것과 비슷했습니다. 새로운 구문을 사용하면 쿼리 최적화 프로그램은 어떤 부분이 함께 진행되는지 파악하기 위해 수행해야 할 작업이 줄어 듭니다.

그래서 당신은 그것을 가지고 있습니다.

LEFT와 INNER JOIN은 미래의 물결입니다.


28
"대부분의 최신 데이터베이스에서는 더 이상 사용되지 않습니다." --- 궁금한 점이 있습니까?
zerkms

10
용서하십시오. * = 연산자에 익숙하지 않습니다. 어떻게해야합니까? 감사!
ultrajohn

9
Star = 및 = Star는 오른쪽 및 왼쪽 외부 조인입니까, 아니면 왼쪽 및 오른쪽입니까? 오래 전부터 더 이상 사용되지 않아 SQL Server 6부터 사용하지 않았습니다.
Tony Hopkinson

3
쉼표는 더 이상 사용되지 않습니다. 절대 표준 OUTER JOIN구문 *=/ =*/ *=*사용되지 않습니다.
philipxy

1
이 답변은 외부 조인이 아닌 질문에 대한 답변조차하지 않습니다. 쉼표 대 INNER JOIN ON ON, 재 최적화에 대한 주장은 잘못되었습니다.
philipxy

17

JOIN 구문은 적용되는 테이블 근처에 조건을 유지합니다. 많은 양의 테이블을 조인 할 때 특히 유용합니다.

그건 그렇고, 첫 번째 구문으로 외부 조인을 수행 할 수도 있습니다.

WHERE a.x = b.x(+)

또는

WHERE a.x *= b.x

또는

WHERE a.x = b.x or a.x not in (select x from b)

2
* = 구문은 MS SQLServer에서 더 이상 사용되지 않으며 그 이유는 다음과 같습니다. 읽기가 더 어려워 질뿐만 아니라 사람들이 생각하는대로하지 않으며 비슷하게 보이는 LEFT JOIN과 동일하지 않습니다. (+) 구문은 익숙하지 않습니다. 어떤 SQL 구현입니까?
Euro Micelli

2
다른 구문은 최소한 Oracle에서 사용합니다.
Lasse V. Karlsen

4
SQL Server 구문 * =을 사용하지 마십시오. 때로는 왼쪽 조인이 아닌 크로스 조인으로 해석되므로 일관된 결과를 제공하지 않습니다. SQL Server 2000까지도 마찬가지입니다.이 코드를 사용하는 코드가 있으면 수정해야합니다.
HLGEM

12

첫 번째 방법은 더 오래된 표준입니다. 두 번째 방법은 SQL-92, http://en.wikipedia.org/wiki/SQL 에 도입되었습니다 . 완전한 표준은 http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt 에서 볼 수 있습니다 .

데이터베이스 회사가 SQL-92 표준을 채택하기까지 몇 년이 걸렸습니다.

따라서 두 번째 방법이 선호되는 이유는 ANSI 및 ISO 표준위원회에 따른 SQL 표준입니다.


,여전히 표준입니다. on필요한 경우에만 도입 할 outer join부속 선택도 도입하면.
philipxy

12

기본적으로 FROM 절에 다음과 같은 테이블이 나열되면

SELECT * FROM
  tableA, tableB, tableC

결과는 테이블 A, B, C에있는 모든 행의 교차 곱입니다. 그런 다음 WHERE tableA.id = tableB.a_id많은 수의 행을 버릴 제한 을 적용한 다음 추가로 AND tableB.id = tableC.b_id관심이있는 행만 가져와야합니다. 에.

DBMS는 JOIN을 사용하여이를 작성하는 것과의 성능 차이가 무시할 수 있도록이 SQL을 최적화하는 방법을 알고 있습니다. JOIN 표기법을 사용하면 SQL 문을 읽기 쉽게 만듭니다 (IMHO, 조인을 사용하지 않으면 명령문이 엉망이됩니다). 교차 곱을 사용하려면 WHERE 절에 조인 기준을 제공해야합니다. 이것이 표기법의 문제입니다. 당신은 WHERE 절을 다음과 같은 것들로 붐비고 있습니다.

    tableA.id = tableB.a_id 
AND tableB.id = tableC.b_id 

교차 제품을 제한하는 데만 사용됩니다. WHERE 절은 결과 집합에 대한 RESTRICTIONS 만 포함해야합니다. 테이블 조인 기준을 결과 집합 제한과 혼합하면 쿼리를 읽기가 더 어려워집니다. 반드시 JOIN을 사용하고 FROM 절을 FROM 절로, WHERE 절을 WHERE 절로 유지해야합니다.


10

두 번째는 where 절을 입력하는 것을 잊어 버려 우연히 교차 결합을 일으킬 가능성이 훨씬 적으므로 선호됩니다. on 절이없는 조인은 구문 검사에 실패하고 where 절이없는 이전 스타일 조인은 실패하지 않으며 교차 조인을 수행합니다.

또한 나중에 왼쪽 조인해야 할 경우 모두 동일한 구조로 유지 관리하는 데 도움이됩니다. 1992 년 이래로 오래된 구문이 오래되었습니다. 사용을 중단 할 시간이 지났습니다.

또한 첫 번째 구문을 독점적으로 사용하는 많은 사람들이 실제로 조인을 이해하지 못하고 조인을 이해하는 것이 쿼리 할 때 올바른 결과를 얻는 데 중요하다는 것을 알았습니다.


6

이 페이지에는 명시 적 JOIN을 사용하는 두 번째 방법을 채택해야 할 몇 가지 이유가 있다고 생각합니다. 그러나 클린 처는 JOIN 기준이 WHERE 절에서 제거 될 때 WHERE 절의 나머지 선택 기준을 훨씬 쉽게 볼 수 있다는 것입니다.

실제로 복잡한 SELECT 문에서 독자는 진행 상황을 훨씬 쉽게 이해할 수 있습니다.


5

SELECT * FROM table1, table2, ...구문은 테이블의 몇 가지에 대한 확인이지만, (기하 급수적하게 반드시 수학적으로 정확한 문장 테이블의 수가 증가함에 따라 읽기 힘들어).

JOIN 구문은 쓰기가 어렵지만 (처음에는) 어떤 기준이 어떤 테이블에 영향을 미치는지 명시 적으로 만듭니다. 이로 인해 실수하기가 훨씬 어려워집니다.

또한 모든 조인이 INNER이면 두 버전이 동일합니다. 그러나 명령문의 어느 곳에서나 OUTER 조인이 발생하면 상황이 훨씬 복잡해지며 실제로 작성한 내용이 작성한 내용을 쿼리하지 않을 것입니다.


2

외부 조인이 필요할 때 두 번째 구문이 항상 필요한 것은 아닙니다 .

신탁:

SELECT a.foo, b.foo
  FROM a, b
 WHERE a.x = b.x(+)

MSSQLServer ( 2000 버전에서는 더 이상 사용되지 않지만 ) / Sybase :

SELECT a.foo, b.foo
  FROM a, b
 WHERE a.x *= b.x

그러나 당신의 질문으로 돌아갑니다. 나는 답을 알고하지 않습니다, 그러나 그것은 아마이 사실과 관련이 조인 A와 식을 추가하는 것보다 (적어도, 구문) 더 자연스러운 경우 : 당신이 정확히하고있는 절 에 합류 .


SQL Server는 왼쪽 조인 구문을 더 이상 사용하지 않으며 SQL Server 2000에서도 올바른 결과를 제공하지 않으며 (때로는 왼쪽 조인 대신 크로스 조인을 수행함) SQL Server에서 사용해서는 안됩니다.
HLGEM

@HLGEM : 정보 주셔서 감사합니다. 나는 당신이 말하는 것을 반영하기 위해 게시물을 업데이트 할 것입니다.
Pablo Santa Cruz

0

많은 사람들이 첫 번째 사람이 이해하기가 어렵고 불분명하다고 불평하는 것을 듣습니다. 나는 그것에 관한 문제를 보지 못했지만 그 토론을 한 후에는 명확성을 위해 INNER JOINS에서도 두 번째 것을 사용합니다.


1
JOIN 구문을 사용하지 않고 첫 번째 방법을 사용하는 습관이 생겼습니다. 나는 종종 두뇌가 그 논리를 따르도록 조절되었다고 생각하기 때문에 종종 습관에 갇혀 있음을 인정해야한다. 나에게 때때로 조인 구문은 생각하기 어려운 것처럼 보인다.
TheTXI

3
나도 그렇게 배웠다. 사람들은 코딩 스타일을 보았고 무슨 일이 일어나고 있는지 쉽게 인식하지 못하기 때문에 코딩 스타일을 변경했습니다. 논리적 차이가없고 후자를 선택하는 이유를 찾을 수 없기 때문에 다른 사람들이 내가 작성한 것을 이해하도록 돕기 위해 코드를 더 명확하게 만드는 데 적응해야한다고 느꼈습니다.
kemiller2002

0

데이터베이스는 결국 동일합니다. 그러나 일부 상황에서는 두 번째 구문을 사용해야합니다. 쿼리를 사용하기 위해 쿼리를 편집하기 위해 (직접 조인이있는 왼쪽 조인이 필요하다는 것을 알았습니다) 일관성을 위해 두 번째 방법에서만 패턴을 지정했습니다. 쿼리를보다 쉽게 ​​읽을 수 있습니다.


0

오른쪽 테이블에 해당 레코드가없는 경우에도 LEFT JOIN에 첫 번째 테이블의 모든 레코드가 포함되므로 첫 번째 쿼리와 두 번째 쿼리의 결과가 서로 다를 수 있습니다.

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