대부분의 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
이제 외부 조인이 필요할 때 두 번째 구문이 필요합니다. 그러나 내부 조인을 수행 할 때 첫 번째 구문보다 두 번째 구문을 선호해야하는 이유는 무엇입니까?
대부분의 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
이제 외부 조인이 필요할 때 두 번째 구문이 필요합니다. 그러나 내부 조인을 수행 할 때 첫 번째 구문보다 두 번째 구문을 선호해야하는 이유는 무엇입니까?
답변:
테이블을 나열 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은 미래의 물결입니다.
OUTER JOIN
구문 *=
/ =*
/ *=*
사용되지 않습니다.
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)
첫 번째 방법은 더 오래된 표준입니다. 두 번째 방법은 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
부속 선택도 도입하면.
기본적으로 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 절로 유지해야합니다.
두 번째는 where 절을 입력하는 것을 잊어 버려 우연히 교차 결합을 일으킬 가능성이 훨씬 적으므로 선호됩니다. on 절이없는 조인은 구문 검사에 실패하고 where 절이없는 이전 스타일 조인은 실패하지 않으며 교차 조인을 수행합니다.
또한 나중에 왼쪽 조인해야 할 경우 모두 동일한 구조로 유지 관리하는 데 도움이됩니다. 1992 년 이래로 오래된 구문이 오래되었습니다. 사용을 중단 할 시간이 지났습니다.
또한 첫 번째 구문을 독점적으로 사용하는 많은 사람들이 실제로 조인을 이해하지 못하고 조인을 이해하는 것이 쿼리 할 때 올바른 결과를 얻는 데 중요하다는 것을 알았습니다.
SELECT * FROM table1, table2, ...
구문은 테이블의 몇 가지에 대한 확인이지만, (기하 급수적하게 반드시 수학적으로 정확한 문장 테이블의 수가 증가함에 따라 읽기 힘들어).
JOIN 구문은 쓰기가 어렵지만 (처음에는) 어떤 기준이 어떤 테이블에 영향을 미치는지 명시 적으로 만듭니다. 이로 인해 실수하기가 훨씬 어려워집니다.
또한 모든 조인이 INNER이면 두 버전이 동일합니다. 그러나 명령문의 어느 곳에서나 OUTER 조인이 발생하면 상황이 훨씬 복잡해지며 실제로 작성한 내용이 작성한 내용을 쿼리하지 않을 것입니다.
외부 조인이 필요할 때 두 번째 구문이 항상 필요한 것은 아닙니다 .
신탁:
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와 식을 추가하는 것보다 (적어도, 구문) 더 자연스러운 경우 : 당신이 정확히하고있는 절 에 합류 .
많은 사람들이 첫 번째 사람이 이해하기가 어렵고 불분명하다고 불평하는 것을 듣습니다. 나는 그것에 관한 문제를 보지 못했지만 그 토론을 한 후에는 명확성을 위해 INNER JOINS에서도 두 번째 것을 사용합니다.