문제

다음 쿼리가 있습니다.

SELECT c.*
FROM companies AS c
JOIN users AS u USING(companyid)
JOIN jobs AS j USING(userid)
JOIN useraccounts AS us USING(userid)
WHERE j.jobid = 123;

다음 질문이 있습니다.

  1. 구문을 사용하는 것은 구문과 동의어입니까?
  2. 이 결합이 왼쪽에서 오른쪽으로 평가 되었습니까? 다시 말해,이 쿼리는 다음과 같이 말합니까 : x = 회사는 사용자 가입; y = x 작업 가입; z = y userAccounts 가입;
  3. 질문 2에 대한 답이 예라면, 회사 테이블에 CompanyID, UserID 및 JobID 열이 있다고 가정하는 것이 안전합니까?
  4. alias "j"를 언급 할 때 Where 절을 사용하여 회사 테이블에서 행을 선택하는 방법을 이해하지 못합니다.

모든 도움이 감사하겠습니다!

도움이 되었습니까?

해결책

  1. 사용 (FieldName) 사용은 표 1.fieldName = table2.fieldName에서 속기있는 방법입니다.

  2. SQL은 언어의 본질이 아니기 때문에 결합 된 '순서'를 정의하지 않습니다. 명확하게 명령문에 명시되어 있어야하지만 내부 조인은 통근으로 간주 될 수 있습니다. 어떤 순서로든 나열 할 수 있으며 동일한 결과를 얻을 수 있습니다.

    즉, Select ... Join, 특히 왼쪽 조인을 포함하는 조인을 구성 할 때, 세 번째 조인이 첫 번째 조인의 결과에 새 테이블에 가입하는 것으로 간주하는 것이 합리적이라는 것을 알았습니다. 두 번째 조인의 결과 등.

    더 드물게, 지정된 순서는 휴리스틱에 영향을 미치는 방식으로 인해 쿼리 최적화의 동작에 영향을 줄 수 있습니다.

  3. 아니요. 쿼리가 조립되는 방식은 회사와 사용자 모두 회사를 가지고 있고, Jobs에는 사용자가 있고, jobid 및 userAccounts에는 userID가 있습니다. 그러나 회사 중 하나만 또는 사용자는 가입하기 위해 userID가 필요합니다.

  4. WHERE 절은 작업 테이블에서 제공하는 열을 사용하여 전체 결과 (즉 모두 결합 된 열)를 필터링합니다.

다른 팁

사용 구문에 대한 비트에 대답 할 수 없습니다. 이상 하네. 나는 항상 그것을 본 적이 없다.

하지만 내가 뭐야 ~할 수 있다 결합 작업 순서는 최적화 휴리스틱 시스템을 기반으로 쿼리 계획을 구성 할 때 쿼리 최적화에 의해 동적으로 결정된다고 말합니다.

  1. Join은 기본 키 필드에서 수행됩니까? 그렇다면 쿼리 계획에서 우선 순위가 높습니다.

  2. 조인은 외국 키 필드에서 수행됩니까? 이것은 또한 우선 순위가 높습니다.

  3. 결합 된 필드에 인덱스가 존재합니까? 그렇다면 우선 순위를 부딪칩니다.

  4. where 절의 필드에서 조인 작업이 수행됩니까? where 절 표현식을 테이블 스캔을 수행하지 않고 지수를 검사하여 평가할 수 있습니까? 이것은 주요한 최적화 기회이므로 주요 우선 순위가 높아집니다.

  5. 가입 된 열의 카디널리티는 무엇입니까? 추기경이 높은 열은 옵티마이즈에 허위 경기 (WHERE 절 또는 ON 절을 만족시키지 않는 것)를 차별 할 수있는 더 많은 기회를 제공하므로, 높은 카디 컬티 결합은 일반적으로 저 카더 인 조인이되기 전에 처리됩니다.

  6. 결합 된 테이블에 얼마나 많은 실제 행이 있습니까? 100 개의 값만으로 테이블에 가입하면 천만 행이있는 테이블에 합류하는 것보다 데이터 폭발이 적습니다.

어쨌든 ... 요점은 ... 쿼리 실행 계획에 들어가는 많은 변수가 있습니다. MySQL이 쿼리를 최적화하는 방법을 보려면 설명 구문을 사용하십시오.

그리고 다음은 읽을 수있는 좋은 기사입니다.

http://www.informit.com/articles/article.aspx?p=377652


편집 :

네 번째 질문에 답하기 위해 : "회사"테이블을 쿼리하지 않습니다. 결합 된 교차 제품을 쿼리하고 있습니다 모두 조항을 사용하는 4 개의 테이블.

"j.jobid"별칭은 테이블 모음에 합류 한 열 중 하나의 완전히 자격이있는 이름 일뿐입니다.

MySQL에서는 다음과 같이 쿼리 최적화기에게 무엇을 해야하는지 묻는 것이 종종 흥미 롭습니다.

EXPLAIN SELECT [...]

보다 "7.2.1 설명으로 쿼리 최적화"

보다 http://dev.mysql.com/doc/refman/5.0/en/join.html

여기에서 읽기 시작하십시오.


MySQL 5.0.12에서 처리 변경에 가입하십시오

MySQL 5.0.12부터 시작하여 외부 결합 변형을 포함한 자연 조인 및 결합은 SQL : 2003 표준에 따라 처리됩니다. 목표는 SQL : 2003에 따라 자연 조인 및 조인과 관련하여 MySQL의 구문과 의미를 정렬하는 것이 었습니다. 그러나 조인 처리의 이러한 변경으로 인해 일부 조인에 대해 출력 열이 다를 수 있습니다. 또한 기존 버전에서 올바르게 작동하는 것으로 보이는 일부 쿼리는 표준을 준수하도록 다시 작성해야합니다.

이러한 변경 사항에는 5 가지 주요 측면이 있습니다.

  • MySQL이 자연의 결과 열을 결정하는 방식 또는 조인 작업을 사용하는 방식 (따라서 전체 조항의 결과)을 결정합니다.

  • 선택 *의 확장 * 및 선택된 열 목록으로 tbl_name을 선택하십시오.

  • 자연 또는 조인 사용에서 열 이름의 해상도.

  • 자연의 변환 또는 결합으로 결합 된 ... on.

  • 조인 조건에서 열 이름의 해상도 ... on.

나는 부품을 사용하는 vs에 대해 확실하지 않습니다 (그러나 이것은 웹 사이트 그들이 동일하다고 말한다)

주문 질문은 전적으로 구현 (및 아마도 쿼리)에 따라 다릅니다. MySQL은 요청을 컴파일 할 때 주문을 선택할 가능성이 높습니다. 특정 순서를 시행하려면 쿼리를 '중첩'해야합니다.

SELECT c.*
FROM companies AS c 
    JOIN (SELECT * FROM users AS u 
        JOIN (SELECT * FROM  jobs AS j USING(userid) 
              JOIN useraccounts AS us USING(userid) 
              WHERE j.jobid = 123)
    )

파트 4 : Where 절은 작업 테이블의 행을 연결할 수있는 곳을 제한합니다. 따라서 일치하는 userids로 인해 결합 될 행이 있지만 올바른 JobID가 없으면 생략됩니다.

1) 사용하는 것은 ON과 정확히 같지 않지만 두 테이블 모두에 합류 한 이름의 열이있는 곳은 짧습니다. http://www.java2s.com/tutorial/mysql/0100__table-join/theywordusingcanbeusedAseareSareArseAReARESAREPAREMENTFORTHEONKEYWORDDURINGTableJoins.htm

내 의견으로는 읽기가 더 어렵 기 때문에 나는 결합을 철자 할 것입니다.

3)이 쿼리에서 명확하지는 않지만 그렇지 않은 것 같습니다.

2) 다른 테이블을 통해 가입한다고 가정하면이 쿼리의 순서는 중요합니다 ... 아래의 비교를 참조하십시오.

오리지널 :

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u USING(companyid) 
    JOIN jobs AS j USING(userid) 
    JOIN useraccounts AS us USING(userid) 
WHERE j.jobid = 123

내가 생각하는 것은 다음과 같이 제안 할 것입니다.

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u on u.companyid = c.companyid
    JOIN jobs AS j on j.userid = u.userid
    JOIN useraccounts AS us on us.userid = u.userid 
WHERE j.jobid = 123

여기에서 Jobs & UsersAccounts 결합 라인을 전환 할 수 있습니다.

모든 것이 회사에 합류하면 어떻게 보일지 :

SELECT c.* 
    FROM companies AS c 
    JOIN users AS u on u.companyid = c.companyid
    JOIN jobs AS j on j.userid = c.userid
    JOIN useraccounts AS us on us.userid = c.userid
WHERE j.jobid = 123

각 사용자가 자신의 회사가없는 한 이것은 논리적으로 의미가 없습니다.

4.) SQL의 마법은 특정 열만 표시 할 수 있지만 모두 정렬 및 필터링을위한 것입니다 ...

돌아온 경우

SELECT c.*, j.jobid....  

필터링이 무엇인지 명확하게 볼 수 있지만 데이터베이스 서버는 연수를 출력하는지 여부를 신경 쓰지 않거나 필터링을 위해 신경 쓰지 않습니다.

다음은 더 자세한 답변입니다 JOIN 상위. 당신의 경우, JOINs는 모두 정류적입니다. 그들이 아닌 곳을 시도해 봅시다.

빌드 스키마 :

CREATE TABLE users (
  name text
);

CREATE TABLE orders (
  order_id text,
  user_name text
);

CREATE TABLE shipments (
  order_id text,
  fulfiller text
);

데이터 추가 :

INSERT INTO users VALUES ('Bob'), ('Mary');

INSERT INTO orders VALUES ('order1', 'Bob');

INSERT INTO shipments VALUES ('order1', 'Fulfilling Mary');

실행 쿼리 :

SELECT *
  FROM users
       LEFT OUTER JOIN orders
       ON orders.user_name = users.name
       JOIN shipments
       ON shipments.order_id = orders.order_id

결과:

Bob Row 만 반환됩니다

분석:

이 쿼리에서 LEFT OUTER JOIN 먼저 평가되었습니다 JOIN 복합 결과에 대해 평가되었다 LEFT OUTER JOIN.

두 번째 쿼리 :

SELECT *
  FROM users
       LEFT OUTER JOIN (
         orders
         JOIN shipments
         ON shipments.order_id = orders.order_id)
         ON orders.user_name = users.name

결과:

Bob의 한 행 (이행 데이터 포함)과 이행 데이터를위한 Nulls가있는 Mary의 행.

분석:

괄호는 평가 순서를 변경했습니다.


또한 MySQL 문서가 있습니다 https://dev.mysql.com/doc/refman/5.5/en/nested-join-optimization.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top