2012-12-05 4 views
1

우리는 NCAA 선수와 그 선수들이 고등학교에 간 곳에 대한 정보를 가지고 있습니다. 우리는 고등학교에 다니는 NCAA 운동 선수의 수에 따라 고등학교를 순위 지정하고 싶습니다.복잡한 MySQL 쿼리 in 레일

우리는 players, teams, team_histories, accountsplayer_to_team_histories 있습니다. account (남자 축구, 여자 배구)의 team은 특정 팀을 나타내며, team (남자 축구, 여자 배구)의 1 년을 나타내는 (2012 년 남자 축구 팀)의 경우 player은 선수 (그들이 자란 고등학생, 이름)의 전기 정보를 나타내며 player_to_team_historyteam_history (연도, 크기, 무게, 위치에 대한 통계)에 player을 나타냅니다.

다음 MySQL 쿼리를 통해 특정 대학의 각 고등학교에서 선수 수에 대한 순위를 추출했습니다. 나는 가장 안쪽 문부터 시작하여, 아래의 쿼리를 무너 뜨리는 것 :

SELECT WrappedQuery.rank FROM 
(SELECT 
    @rownum := @rownum+1 AS rank, q.Name, q.id 
FROM  
    (SELECT @rownum := 0) counter, 
    (SELECT 
     Accounts.id, Accounts.Name, COUNT(Accounts.Name) AS count 
    FROM 
     player_to_team_histories 
    INNER JOIN team_histories ON team_histories.id = player_to_team_histories.team_history_id 
    INNER JOIN teams ON teams.id = team_histories.team_id 
    INNER JOIN accounts ON accounts.id = teams.account_id 
    WHERE 
     accounts.AccountTypeId = 1 AND player_id IN (SELECT 
      player_id 
     FROM 
      player_to_team_histories 
     WHERE 
      player_to_team_histories.not_valid IS NULL AND team_history_id = (SELECT 
       team_history_id 
      FROM 
       player_to_team_histories 
      INNER JOIN team_histories ON team_histories.id = player_to_team_histories.team_history_id 
      WHERE 
       player_to_team_histories.id = 574651)) 
    GROUP BY Accounts.Name 
    ORDER BY count DESC) q) WrappedQuery 
WHERE WrappedQuery.id = 7661 

팀 역사에게 ID를

SELECT 
    team_history_id 
FROM 
    player_to_team_histories 
     INNER JOIN 
    team_histories ON team_histories.id = player_to_team_histories.team_history_id 
WHERE 
    player_to_team_histories.id = 574651 

이 있습니다 우리가 관심있는 대학 팀의 team_history_id를 추출 모든 팀원이 동일한 team_history_id를 갖기 때문에 우리가 선택한 플레이어 (player_to_team_history.id = 574651로 식별)에 팀원을 얻으십시오.

팀원은

SELECT 
    player_id 
FROM 
    player_to_team_histories 
WHERE 
    player_to_team_histories.not_valid IS NULL AND team_history_id = (SELECT 
     team_history_id 
    FROM 
     player_to_team_histories 
      INNER JOIN 
     team_histories ON team_histories.id = player_to_team_histories.team_history_id 
    WHERE 
     player_to_team_histories.id = 574651) 

우리는 선택한 플레이어의 팀 동료 모두를 얻기 위해 그 team_history_id를 사용합니다. 그런 다음 플레이어를 사용하여 고등학교를 찾습니다.

고등학교 팀은 우리가에 관심이있는 모든 선수에 대한 높은 학교 (accounts.AccountTypeId = 1)와 관련된 player_to_team_history를 잡아함으로써

SELECT 
    Accounts.id, Accounts.Name, COUNT(Accounts.Name) AS count 
FROM 
    player_to_team_histories 
     INNER JOIN 
    team_histories ON team_histories.id = player_to_team_histories.team_history_id 
     INNER JOIN 
    teams ON teams.id = team_histories.team_id 
     INNER JOIN 
    accounts ON accounts.id = teams.account_id 
WHERE 
    accounts.AccountTypeId = 1 AND player_id IN (SELECT 
     player_id 
    FROM 
     player_to_team_histories 
    WHERE 
     player_to_team_histories.not_valid IS NULL AND team_history_id = (SELECT 
      team_history_id 
     FROM 
      player_to_team_histories 
       INNER JOIN 
      team_histories ON team_histories.id = player_to_team_histories.team_history_id 
     WHERE 
      player_to_team_histories.id = 574651)) 
GROUP BY Accounts.Name 
ORDER BY count DESC 

, 우리는 팀 동료에서 연주하는 고등학교, 그룹을하여을 찾을 수 있습니다 accounts.id을 입력 한 다음 각 그룹 수를 기준으로 정렬하여 대학 순위에 가장 많은 고등학교가있는 정렬 목록을 제공합니다.

RANKING

SELECT WrappedQuery.rank FROM 
(SELECT 
    @rownum := @rownum+1 AS rank, q.Name, q.id 
FROM  
    (SELECT @rownum := 0) counter, 
    (SELECT 
     Accounts.id, Accounts.Name, COUNT(Accounts.Name) AS count 
    FROM 
     player_to_team_histories 
    INNER JOIN team_histories ON team_histories.id = player_to_team_histories.team_history_id 
    INNER JOIN teams ON teams.id = team_histories.team_id 
    INNER JOIN accounts ON accounts.id = teams.account_id 
    WHERE 
     accounts.AccountTypeId = 1 AND player_id IN (SELECT 
      player_id 
     FROM 
      player_to_team_histories 
     WHERE 
      player_to_team_histories.not_valid IS NULL AND team_history_id = (SELECT 
       team_history_id 
      FROM 
       player_to_team_histories 
      INNER JOIN team_histories ON team_histories.id = player_to_team_histories.team_history_id 
      WHERE 
       player_to_team_histories.id = 574651)) 
    GROUP BY Accounts.Name 
    ORDER BY count DESC) q) WrappedQuery 
WHERE WrappedQuery.id = 7661 

우리는. 우리의 순위의 각 행 번호와 우리가 관심있는 행을 잡아서 마무리이 경우, 우리는 그 통해 AccountId 7661.이있는 고등학교에 관심 선택된 선수가 참석 한 고등학교입니다. 그러면 고등학교가 선정 된 현재 대학 명단에 선수를 기여한 모든 고등학교 중 학교에 알려줍니다. 내가 잃어버린하고 어디

레일

에서이 작업을 수행하는 방법이다. 이러한 중첩 된 조인/하위 쿼리와 순위 결과를 어떻게 처리합니까?

이 문제에 접근하는 것은 끔찍한 방법 일 수 있습니다. 이것을 여러 개의 쿼리로 나누고 모든 것을 레일스에서 ​​다시 스티치하는 것이 더 낫지 않습니까?

select_by_sql을 수행하지 않으면 Rails를 사용하여 쉽게 처리 할 수 ​​있습니까?

VERSIONS이 AREL을 사용하여 수행 할 수 있지만, 파고를 많이 필요로

Rails 3.2.1 
Ruby 1.9.2 

답변

0

. 하지만 제가 과거에 사용했던 것은 훨씬 더 쉽게 하위 쿼리를 만드는 것은 Squeel가 액티브 더 접근 아래에 놓여 ARel의 awesomeness를함으로써, 루비를 더 적은 문자열을 사용하여 액티브 쿼리를 작성할 수 있습니다, 그리고 더 "squeel

을 사용하는 것입니다 . "

0

이 질문에 대한 답변이 정확하지는 않지만 문제 해결을 위해이 방법을 사용해보십시오.

기존 SQL 쿼리를 사용하고 SQL 템플릿 gem을 사용하십시오.

Yesql을 기반으로하는 Yayql 과 같은 형식으로 시도 할 수 있지만 텍스트 또는 SQL 템플릿 엔진이 수행 할 수 있습니다.