Rails中复杂的MySQL查询

时间:2012-12-05 19:01:07

标签: mysql ruby-on-rails activerecord

我们有关于NCAA运动员的信息以及这些运动员上高中的地方。我们希望按照参加高中的NCAA运动员数量对高中进行排名。

我们有playersteamsteam_historiesaccountsplayer_to_team_historiesaccount表示学校(姓名,地点,类型(大学,高中)),team描述account(男子足球,女子排球)的特定球队,team_history {1}}代表特定team(2012年男子足球队)的一年,player代表运动员的传记信息(他们长大的地方,他们就读的高中,他们的名字) ),player_to_team_history表示player上的team_history(年份,大小,重量,位置的统计数据)。

我已经制定了以下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,这样我们就可以让队友为我们选中的球员(由player_to_team_history.id = 574651识别),因为所有队友都拥有相同的team_history_id

队友

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来获取所选玩家的所有队友。然后我们使用球员找到他们的高中。

高中团队

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

通过抓住与我们感兴趣的所有玩家相关的高中player_to_team_historyaccounts.AccountTypeId = 1),我们可以找出队友所在的哪些高中,按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的高中。这是所选参与者所在的高中,这是将告诉我们,在所有为当前大学名单贡献球员的高中,我们选择的球员高中排名。

如何在Rails中执行此操作

这是我迷失的地方。我如何进行这些嵌套连接/子查询和结果排名?

我完全理解这可能是解决这个问题的可怕方法。将它分解为多个查询并将所有内容拼接在Rails中会不会更好?

没有做select_by_sql,是否有任何地方可以使用Rails使这更容易?

VERSIONS

Rails 3.2.1
Ruby 1.9.2 

2 个答案:

答案 0 :(得分:0)

这可以使用AREL完成,但需要大量挖掘。但是我过去用来使子查询更容易的是使用squeel

“Squeel允许您使用更少的字符串来编写ActiveRecord查询,并通过使ActiveRecord下面的ARel功能更易于访问来编写更多Ruby。”

答案 1 :(得分:0)

虽然这不能完全回答您的问题,但我建议您尝试这样来解决您的问题。

获取现有SQL查询并使用SQL模板gem。

您可以尝试Yayql之类的内容 它基于Yesql,但任何文本或SQL模板引擎都可以。