2016-09-13 2 views
0

SQL에서 쿼리를 작성하여 경력에서 500 홈런 이상을 기록한 35 세의 플레이어 홈런 합계를 가져옵니다.SQL 쿼리 테이블 조인 및 절

SELECT b.playerID, b.yearID, b.HR 
FROM batting b 
JOIN master m ON m.playerID = b.playerID 
WHERE b.yearID - m.birthYear = '35' 
HAVING SUM(b.HR) > 500 

이 쿼리는 실행하는 동안 시간이 초과됩니다. 특정 연령대의 플레이어의 홈런 합계를 반환하는 쿼리를 성공적으로 만들었습니다. 나는 또한 500 홈런 클럽에서 선수를 돌려 줄 수있는 쿼리를 성공적으로 만들었습니다.

내가 그들을 결합하려고하면 뭔가 시간이 초과되어 왜 그럴 수 없는지 알 수 없습니다. 난 단지이 결과 500 개 경력 홈런 만 그 선수를 반환 탑재 되 수 있다면 지금

SELECT b.playerID, b.yearID, b.HR 
FROM batting b 
JOIN MASTER M ON b.playerID = m.playerID 
WHERE b.yearID - m.birthYear = 35 AND b.yearID = 2015 
ORDER BY b.HR DESC 

: 여기

잘 작동하는 쿼리입니다. 012 홈 경기 타격 자의 총 인원은 2015 년입니다.

+2

힌트 :이 쿼리에는'GROUP BY'가 필요합니다. –

+0

반드시 35 세의 나이는 아니 겠지? – Strawberry

+0

500 HR 클럽의 모든 회원에 대해 35 시즌 HR 총계를 가져 가고 싶습니다. – lmoquin

답변

0

가장 가능성있는 설명은 옵티마이 저가 선택한 실행 계획이 효율적이지 않다는 것입니다.

표시되지 않는 것은이 테이블에서 사용할 수있는 색인입니다. 쿼리에 대해 눈에 띄는

것은 이것이다 :

WHERE b.yearID - m.birthYear = '35' 

MySQL이 때문에 (같은 player_id로 batting에서 모든 행에 그 주어진 player_id와 master에서 모든 행을 가지고 일치하는 것입니다 평등 가입 조건)

ON m.playerID = b.playerID 

그리고 MySQL이 가지고 결합 행의 설정을 한 다음이 표현

을 계산

그런 다음 그 결과를 '35'와 비교하십시오.

playerID 열이 master 테이블 우리는 (playerID,yearID)의 열을 선도하는 것을 batting에 인덱스를 활용할 수있는 형태로 작성된 쿼리 조건을보고 선호하는 것

에서 고유이라고 가정.

SELECT b.playerid 
     , b.yearid 
     , SUM(b.hr) AS hr 
    FROM master m 
    JOIN batting b 
    ON b.playerid = m.playerid 
    AND b.yearid = m.birthyear + 35 
    GROUP BY b.playerid, b.yearid 
HAVING SUM(b.hr) > 500 
ORDER BY SUM(b.hr) DESC 

각 플레이어에 대해 반환되는 행을 가져 오려면 GROUP BY 절이 필요합니다. 총 홈런을 얻으려면 SELECT 목록에 SUM() 집계가 필요합니다. playeridmaster 테이블에 고유하지 않으면

쿼리의 최적의 성능을

, 당신이 포함하는 인덱스

... ON batting (playerid, yearid, hr) 

을 싶어, 다음 쿼리는 당신이 기대하는 가치를 보장하지 않을 SUM (b.hr)이면 예상되는 값의 double, triple 등이 될 수 있습니다.

실행 계획을 보려면 EXPLAIN을 사용하십시오.

또한 실행 계획에 부정적인 영향을 줄 수있는 암시 적 데이터 유형 변환에주의하십시오. 두 테이블의 playerid 열의 데이터 유형이 일치하고 yearidbirthyear 열의 데이터 유형이 숫자라고 가정합니다.

편집

내 원래 대답이 쿼리는 "시간 초과"이유에 초점을 맞추고, 나는 당신이 달성하고자하는 결과에 대한 사양을 놓친되었습니다 경력을 가지고

반환 선수 총계 500 이상이며 해당 선수 각각에 대해 특정 연도에 개의 인적 자원을 반환하십시오.

(I 적절 선수가 35 세를 회전하는 "년"을 결정하는 논의를 따로 설정하고, 원래의 쿼리에서 기준을 사용합니다.)

한 가지 방법은 조건 을 사용하는 것입니다 집합. 조건이 TRUE이면 HR을 반환하는 식을 사용하고 그렇지 않으면 0 또는 NULL을 반환합니다. 그런 다음 해당 식을 SELECT 목록의 SUM 집계로 래핑하십시오.

우리는 모든 선수에 대한 행을 반환하려면 ...

SELECT b.playerid 
     , MAX(IF(b.yearid = m.birthyear + 35,b.yearid,NULL)) AS yearid 
     , SUM(IF(b.yearid = m.birthyear + 35, b.hr, 0)) AS year_hr 
    FROM master m 
    JOIN batting b 
    ON b.playerid = m.playerid 
    GROUP BY b.playerid 
HAVING SUM(b.hr) > 500 
    AND MAX(IF(b.yearid = m.birthyear + 35,b.yearid,NULL)) IS NOT NULL 
ORDER BY ... 

를 500 이상 경력 인사 총 플레이어 행을 반환하고 지정된 연도의 batting 적어도 하나 개의 행을 갖고 싶어 경력 HR이 500을 넘는 경우 batting에 지정된 yearid의 행이없는 경우에도 HAVING 절의 두 번째 조건을 생략하도록 쿼리를 조정할 수 있으며 SELECT 목록에서 expression m.birthyear + 35를 사용할 수 있습니다

SELECT b.playerid 
     , MAX(m.birthyear + 35) AS yearid 
     , SUM(IF(b.yearid = m.birthyear + 35, b.hr, 0)) AS year_hr 
    FROM master m 
    JOIN batting b 
    ON b.playerid = m.playerid 
    GROUP BY b.playerid 
HAVING SUM(b.hr) > 500 
ORDER BY ... 

경력 HR 합계가 정확히 500 인 플레이어는 제외됩니다.

+0

이 방법을 사용했으며 공백 결과가 반환됩니다. 개별적으로 실행되도록 각 쿼리를 가져올 수 있지만 조합 할 때 작동하지 않는 것 같습니다. – lmoquin

+0

어쨌든, 사양을 놓쳤습니다. * career * HR 총계가 500 이상 (?과 같지 않은) 플레이어를 반환하고 각 플레이어에 대해 해당 연도의 총 HR 총계를 반환하고자합니다. 내 대답의 원래 쿼리는 특정 계절에 HR이 500 명이 넘는 플레이어 만 반환합니다. 당신이 원하는 쿼리를 포함하도록 내 대답을 편집합니다. – spencer7593

+0

나는 35 세의 나이에 500 타점을 기록한 선수를 얼마나 많이 홈런으로보고 싶습니다. – lmoquin