JOIN 또는 WHERE 내의 조건


194

JOIN 절에 WHERE 절에 조건을 넣는 것 사이에 차이 (성능, 모범 사례 등)가 있습니까?

예를 들어 ...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

당신은 어느 것을 선호합니까?


4
두 개의 쿼리를 실행 했습니까? 두 쿼리에서 생성 된 실행 계획을 확인 했습니까? 무엇을 관찰 했습니까?
S.Lott

22
@ S.Lott,이 쿼리는 예제 목적으로 만 사용됩니다. 나는 "일반적으로"이것이 선호되는 방법 인 것이 궁금하다.
Steve Dignan

1
@Steve Dignan : 샘플 데이터로이를 벤치마킹하고 쿼리 계획을 살펴 봐야합니다. 대답은 매우 명확합니다. 그리고 보너스는 더 복잡한 상황이 발생할 때 재사용 할 수있는 코드입니다.
S.Lott 2016 년

1
조건이 관계를 설명하는 경우 개인적으로 조건을 JOIN 절에 넣습니다. 결과 집합 만 필터링하는 일반 조건은 WHERE 파트로 이동합니다. 예 :FROM Orders JOIN OrderParties ON Orders.Id = OrderParties.Order AND OrderParties.Type = 'Recipient' WHERE Orders.Status = 'Canceled'
Glutexo

답변:


154

관계형 대수를 사용하면 WHERE절과 의 술어를 교환 할 수 INNER JOIN있으므로 절이있는 INNER JOIN쿼리 조차도 WHERE옵티 마이저에 의해 술어가 재 배열되어 프로세스 중에 이미 제외 될 수 있습니다JOIN .

가장 읽기 쉬운 방법으로 쿼리를 작성하는 것이 좋습니다.

때로는 여기에는 INNER JOIN상대적으로 "불완전한"작성 및 WHERE필터링 기준 목록을보다 쉽게 ​​유지 보수 할 수 있도록하기 위해 일부 기준을 포함시키는 것이 포함됩니다.

예를 들어,

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

쓰다:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

그러나 그것은 물론 다릅니다.


7
깨끗한 쿼리 또는 가독성뿐만 아니라 성능에 관한 것입니다. 조인 조건을 설정하면 적절하게 인덱스 된 테이블이있는 대량의 데이터에 대한 성능이 향상됩니다.
Shahdat

1
방금 5 백만 개의 테이블에 수백만 건의 레코드를 결합한 월별 판매 보고서를 실행했습니다. 성능 향상
-SQL

2
@Shahdat 필터 조건을 where 절에서 내부 조인으로 옮기는 성능 차이가 큰 경우 해당 실행 계획을 게시해야합니다.
Cade Roux

4
@Cade 저는 실행 계획을 조사했습니다. 두 시나리오 모두 동일한 비용을 보여줍니다. 쿼리를 여러 번 실행하면 시간이 거의 걸리는 것 같습니다. 이전에는 프로덕션에서 쿼리를 실행하고 있었고 데이터베이스를 실제 사용자가 사용하고 있었기 때문에 성능에 큰 차이가있었습니다. 혼란을 드려 죄송합니다.
Shahdat

4
이 답변은 INNER JOIN에는 적합하지만 왼쪽 / 오른쪽 조인에는 적합하지 않습니다.
sotn

123

내부 조인의 경우 실제로 차이를 느끼지 못했습니다 (그러나 모든 성능 조정과 마찬가지로 조건에 따라 데이터베이스를 확인해야합니다).

그러나 왼쪽 또는 오른쪽 조인을 사용하는 경우 조건을 배치하는 위치에 큰 차이가 있습니다. 예를 들어 다음 두 쿼리를 고려하십시오.

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'

첫 번째는 2009 년 5 월 15 일 이후의 주문이있는 레코드 만 제공하므로 왼쪽 조인을 내부 조인으로 변환합니다.

두 번째는 해당 레코드와 주문이없는 고객을 제공합니다. 조건 설정 위치에 따라 결과 집합이 매우 다릅니다. (선택 *은 예제 목적으로 만 사용되며, 프로덕션 코드에서는 사용하지 않아야합니다.)

한 테이블의 레코드 만보고 다른 테이블은보고 싶지 않은 경우는 예외입니다. 그런 다음 조인이 아닌 조건에 where 절을 사용하십시오.

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null

예를 들어 설명 해주셔서 감사합니다.
조셉 조셉에게

1
"왼쪽 조인을 내부 조인으로 변환" 어떻게? 좀 더 정교하게 할 수 있습니까?
user1451111

@ user1451111 LEFT / RIGHT JOIN이 리턴하는 내용을 학습하십시오. INNER JOIN 행과 일치하지 않는 왼쪽 / 오른쪽 테이블 행은 널 (NULL)로 확장됩니다. FULL JOIN은 INNER JOIN 행을 반환합니다. UNION 모든 일치하지 않는 왼쪽 및 오른쪽 테이블 행을 NULL로 확장합니다. 외부 참여의 일부로 원하는 내부 참여를 항상 알고 있어야합니다. OUTER JOIN ON 후 NULL 확장 열이 NULL이 아니어야하는 WHERE 또는 ON은 NULL로 확장 된 행을 제거합니다. 즉, INNER JOIN 행만 남습니다. 즉 "OUTER JOIN을 INNER JOIN으로 바꿉니다".
philipxy

1
@ user1451111 또는 더 간단한 용어 : A left join BA의 모든 행이 B의 모든 일치하는 행에 조인되었습니다. B에 일치하는 행이없는 경우 A 열에는 값이 있지만 해당 행의 B의 모든 열은 NULL 값으로 표시됩니다. 작성한 경우 where B.somecolumn = ‘somevalue’'somevalue'와 비교되는 NULL (B.somecolumn)이 있습니다. NULL과 비교되는 것은 false이므로 A 행에 대해 일치하는 B 행이없는 모든 행이 제거되고 얻은 결과는 INNER JOIN이 제공하는 결과와 동일하므로 외부 조인은 내부가됩니다.
Caius Jard

예, 결과가 동일하다는 것을 확인했습니다 : SELECT fund.id, prospects.id funds(prospects.id = fund.lead_id and prospects.is_manual = 'no')의 내부 조인 전망 및 SELECT fund.id, prospects.id FROM fundsleft prospects.is_manual = 'no'에서 잠재 고객 참여 (prospects.id = fund.lead_id)
Rohit Dhiman

25

대부분의 RDBMS 제품은 두 쿼리를 동일하게 최적화합니다. Peter Gulutzan과 Trudy Pelzer의 "SQL Performance Tuning"에서 여러 브랜드의 RDBMS를 테스트했지만 성능 차이는 없었습니다.

조인 조건을 쿼리 제한 조건과 별도로 유지하는 것이 좋습니다.

OUTER JOIN때때로 사용하는 경우 join 절에 조건을 넣어야합니다.


1
나는 구문 적으로 그것이 더 깨끗하다는 것에 동의합니다. 나는 그 책에 대한 당신의 지식과 당신의 높은 명성을 연기해야하지만, 지난 주에 매우 다른 실행 계획, CPU 시간 및 논리적 읽기와 함께 4 개의 쿼리를 생각할 수 있습니다 술어를 조인의 위치로 옮겼습니다.
marr75 2016 년

2
모범 사례에 대해 질문했습니다. 특정 RDBMS 구현의 작동 방식을 테스트하자마자 다른 사람들은 올바른 조언을 제공했습니다. 벤치 마크.
Bill Karwin

12

JOIN이 발생한 후 WHERE가 필터링됩니다.

JOIN 프로세스 중에 행이 추가되지 않도록 JOIN을 필터링하십시오.


10
의미 적으로 INNER JOIN 프로세스 중에는 방지되지만 옵티마이 저는 INNER JOIN 및 WHERE 술어를 마음대로 재 배열 할 수 있으므로 옵티마이 저는 원하는 경우 나중에이를 자유롭게 제외 할 수 있습니다.
Cade Roux

1
케이드 루 : 맞습니다. 종종 SQL로 작성하는 것이 모든 것이 말되고 완료 될 때 옵티마이 저가 제공하는 것이 아닙니다. 나는 당신의 대답은 : 자동 쿼리 최적화의 세계에서 물론 더 정확하다 동안이, 모든 이론의 세계에서 잘 될 것이라고 다음 가정 것
TheTXI

나는의 조건의 설명처럼ON
로버트 호샤

3

JOIN이 전체 테이블 / 뷰를 조인 한 다음 결과 집합의 조건자를 소개하기 위해 WHERE를 사용하는 것이 좋습니다.

문법적으로 더 깨끗합니다.


2

일반적으로 조인을 필터링 할 때 성능이 향상됩니다. 특히 두 테이블 모두에 대해 인덱스 열을 조인 할 수있는 경우. 대부분의 쿼리에서도이 작업을 수행하는 논리적 읽기를 줄일 수 있어야합니다. 즉, 대량 환경에서는 실행 시간보다 성능이 훨씬 뛰어납니다.

누군가가 SQL 벤치마킹을 보여줄 때 개발자 서버에서 자정에 sproc 50,000 번의 두 버전을 실행하고 평균 시간을 비교할 때 나는 항상 온화하게 즐겁습니다.


0

조인에 조건을 넣는 것은 "의미 적으로"잘못된 것 같습니다. 왜냐하면 JOIN은 "for"가 아닙니다. 그러나 그것은 매우 질적입니다.

추가 문제 : 내부 조인에서 오른쪽 조인으로 전환하기로 결정한 경우 조인 내에 조건이 있으면 예기치 않은 결과가 발생할 수 있습니다.


3
때로는 이러한 결과가 다소 "예상"되고 때로는 "의도적"입니다 (예 : WHERE 조건이 JOIN 조건과 다른 의미를 갖는 외부 조인의 경우).
Marcel Toth

0

큰 테이블이 있으면 조인이 더 빠릅니다. 특히 작은 테이블을 다루는 경우에는 큰 차이가 없습니다. 조인에 대해 처음 배웠을 때 조인의 조건은 where 절 조건과 같으며 where 절이 조건을 수행 할 테이블에 대해 구체적 인 경우 조건을 상호 교환 적으로 사용할 수 있다고 들었습니다.


-4

조인에 조건을 추가하는 것이 좋습니다. 가독성보다 성능이 더 중요합니다. 큰 데이터 세트의 경우 중요합니다.


1
언급 된 술어의 배치가 성능에 어떤 영향을 미치는지에 대한 증거가 있습니까?
Zso December
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.