[sql] INNER JOIN ON vs WHERE 절

간단하게하기 위해 모든 관련 필드가이라고 가정합니다 NOT NULL.

넌 할 수있어:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

그렇지 않으면:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

이 두 가지가 같은 방식으로 작동 MySQL합니까?



답변

INNER JOIN 사용해야하는 ANSI 구문입니다.

일반적으로 많은 테이블을 조인 할 때 더 읽기 쉬운 것으로 간주됩니다.

OUTER JOIN필요할 때마다 쉽게 교체 할 수 있습니다 .

WHERE구문은 더 관계형 모델을 지향한다.

두 테이블 JOINed 의 결과는 결합 열이 일치하는 행만 선택하는 필터가 적용되는 테이블의 데카르트 곱입니다.

WHERE구문으로 쉽게 볼 수 있습니다.

예를 들어, MySQL (및 일반적으로 SQL)에서이 두 쿼리는 동의어입니다.

또한 MySQL에는 STRAIGHT_JOIN절이 있습니다.

이 절을 사용하여 JOIN순서를 제어 할 수 있습니다 . 외부 루프에서 스캔되는 테이블과 내부 루프에있는 테이블.

WHERE구문을 사용하여 MySQL에서는이를 제어 할 수 없습니다 .


답변

다른 사람들은 INNER JOIN인간의 가독성 을 돕는 것으로 지적했으며 , 이것이 최우선 과제라고 동의합니다. 조인 구문이 더 읽기 쉬운 이유
를 설명하려고합니다 .

기본 SELECT쿼리는 다음과 같습니다.

SELECT stuff
FROM tables
WHERE conditions

SELECT조항은 우리가 무엇 을 되찾고 있는지 알려줍니다 . FROM절은 우리에게 어디 우리가에서 그것을 얻고, 그리고 WHERE절은 우리에게 이야기 하는 우리가 얻고있는 것.

JOIN 테이블에 대한 설명이며, 테이블이 개념 상 실제로는 단일 테이블로 결합되는 방식에 대한 설명입니다.

테이블을 제어하는 ​​쿼리 요소 (우리가 물건을 가져 오는 위치)는 의미 적으로 FROM절에 속합니다 (물론 JOIN요소가 있는 위치 ). 조인 요소를 WHERE절에 넣으면 whichwhere-from을 병합 하므로 JOIN구문이 선호됩니다.


답변

ON / WHERE에서 조건문 적용

여기에서는 논리적 쿼리 처리 단계에 대해 설명했습니다.


참조 : Microsoft® SQL Server ™ 2005 T-SQL 쿼리
게시자 : Microsoft Press
Pub 날짜 : 2006 년 3 월 7 일
ISBN-10
인쇄 : 0-7356-2313-9 ISBN-13 인쇄 : 978-0-7356-2313-2
페이지 : 640

Microsoft® SQL Server ™ 2005 T-SQL 쿼리 내부

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

다른 프로그래밍 언어와 다른 SQL의 첫 번째 눈에 띄는 부분은 코드가 처리되는 순서입니다. 대부분의 프로그래밍 언어에서 코드는 작성된 순서대로 처리됩니다. SQL에서 처리되는 첫 번째 절은 FROM 절이며 가장 먼저 나타나는 SELECT 절은 거의 마지막에 처리됩니다.

각 단계는 다음 단계의 입력으로 사용되는 가상 테이블을 생성합니다. 이 가상 테이블은 호출자 (클라이언트 응용 프로그램 또는 외부 쿼리)에서 사용할 수 없습니다. 마지막 단계에서 생성 된 테이블 만 호출자에게 리턴됩니다. 쿼리에 특정 절을 지정하지 않으면 해당 단계를 건너 뜁니다.

논리적 쿼리 처리 단계에 대한 간략한 설명

단계에 대한 설명이 현재 이해가되지 않는 경우 너무 걱정하지 마십시오. 이들은 참조로 제공됩니다. 시나리오 예제 다음에 나오는 섹션에서는 단계를 훨씬 자세히 설명합니다.

  1. FROM : FROM 절의 처음 두 테이블간에 카티 전 곱 (크로스 조인)이 수행되어 가상 테이블 VT1이 생성됩니다.

  2. ON : ON 필터가 VT1에 적용됩니다. <join_condition>TRUE 인 행만 VT2에 삽입됩니다.

  3. OUTER (join) : OUTER JOIN이 지정되면 (CROSS JOIN 또는 INNER JOIN과 대조적으로) 일치하지 않은 보존 된 테이블 또는 테이블의 행이 VT2의 행에 외부 행으로 추가되어 생성됩니다. VT3. FROM 절에 두 개 이상의 테이블이 나타나면 모든 테이블이 처리 될 때까지 FROM 절의 마지막 조인 결과와 다음 테이블 사이에 1 단계부터 3 단계까지 반복적으로 적용됩니다.

  4. WHERE : WHERE 필터는 VT3에 적용됩니다. <where_condition>TRUE 인 행만 VT4에 삽입됩니다.

  5. GROUP BY : VT4의 행은 GROUP BY 절에 지정된 열 목록을 기준으로 그룹으로 정렬됩니다. VT5가 생성됩니다.

  6. 큐브 | 롤업 : 수퍼 그룹 (그룹 그룹)이 VT5의 행에 추가되어 VT6을 생성합니다.

  7. HAVING : HAVING 필터가 VT6에 적용됩니다. <having_condition>TRUE 인 그룹 만 VT7에 삽입됩니다.

  8. SELECT : SELECT 목록이 처리되어 VT8이 생성됩니다.

  9. DISTINCT : VT8에서 중복 행이 제거되었습니다. VT9가 생성됩니다.

  10. ORDER BY : VT9의 행은 ORDER BY 절에 지정된 열 목록에 따라 정렬됩니다. 커서가 생성됩니다 (VC10).

  11. TOP : 지정된 행 수 또는 백분율이 VC10의 시작부터 선택됩니다. 테이블 VT11이 생성되어 호출자에게 리턴됩니다.


따라서 (INNER JOIN) ON은 WHERE 절을 적용하기 전에 데이터를 필터링합니다 (VT의 데이터 수는 여기에서 줄어 듭니다). 후속 조인 조건은 필터링 된 데이터로 실행되어 성능이 향상됩니다. 그런 다음 WHERE 조건 만 필터 조건을 적용합니다.

(ON / WHERE에 조건문을 적용해도 몇 가지 경우에 큰 차이는 없습니다. 이는 조인 한 테이블 수와 각 조인 테이블에서 사용 가능한 행 수에 따라 다릅니다)


답변

암시 적 조인 ANSI 구문은 오래되었으며 덜 명확하고 권장되지 않습니다.

또한 관계형 대수는 WHERE절과의 술어를 교환 할 수 INNER JOIN있으므로 절이있는 INNER JOIN쿼리 조차도 WHERE최적화 프로그램에 의해 술어가 재 배열 될 수 있습니다.

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

때로는 여기에는 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

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


답변

암시 적 조인 (첫 번째 쿼리라고도 함)은 쿼리에 테이블을 더 추가하기 시작하면 훨씬 더 혼란스럽고 읽기 어려우며 유지 관리하기가 어렵습니다. 4-5 개의 서로 다른 테이블에서 동일한 쿼리 및 조인 유형을 수행한다고 상상해보십시오. 그것은 악몽입니다.

명시 적 조인 (두 번째 예)을 사용하면 훨씬 읽기 쉽고 유지 관리가 쉽습니다.


답변

또한 이전 구문을 사용하면 오류가 발생할 수 있습니다. ON 절없이 내부 조인을 사용하면 구문 오류가 발생합니다. 이전 구문을 사용하고 where 절에서 결합 조건 중 하나를 잊어 버리면 교차 결합을 얻게됩니다. 개발자는 종종 조인 자체가 손상되었다는 사실을 알지 못하기 때문에 조인을 수정하지 않고 구별 키워드를 추가하여 문제를 해결하지만 쿼리 속도를 상당히 늦출 수 있습니다.

또한 이전 구문에서 크로스 조인이있는 경우 유지 관리를 위해 유지 관리자는 크로스 조인이 필요한 상황이 있는지 또는 수정해야하는 사고인지 여부를 어떻게 알 수 있습니까?

왼쪽 조인을 사용하는 경우 암시 적 구문이 왜 나쁜지 알아 보려면이 질문에 대해 설명하겠습니다.
Sybase * = 동일한 내부 테이블에 대해 2 개의 서로 다른 외부 테이블이있는 Ansi Standard

또한 명시 적 조인을 사용하는 표준은 20 년이 넘었으므로 20 년 동안 암시 적 조인 구문이 오래되었습니다. 20 년이 지난 구식 구문을 사용하여 응용 프로그램 코드를 작성 하시겠습니까? 왜 데이터베이스 코드를 작성 하시겠습니까?


답변

그것들은 사람이 읽을 수있는 의미가 다릅니다.

그러나 쿼리 옵티 마이저에 따라 머신과 동일한 의미를 가질 수 있습니다.

항상 읽을 수 있도록 코드를 작성해야합니다.

즉, 이것이 기본 제공 관계인 경우 명시 적 조인을 사용하십시오. 약하게 관련된 데이터와 일치하는 경우 where 절을 사용하십시오.