Как я могу уменьшить размер этого рангового запроса в MySql? - PullRequest
1 голос
/ 05 августа 2010

У меня есть запрос на ранжирование, который оценивает эффективность команд в соревнованиях.

Иерархия данных выглядит следующим образом: команды состоят из членов, члены имеют действия, действия имеют типы действий, задачи имеют типы деятельности

Если я хочу оценить производительность всех команд в одной задаче, этот запрос прекрасно работает:

SELECT     t.teamID, t.teamName, 
        scoring.challengeID, 
        outerchallenge.name AS ChallengeName, outerchallenge.description AS ChallengeDescription, outerchallenge.startDate, outerchallenge.endDate, 
        scoring.standardValueSum, scoring.standardUnit, scoring.rank 
FROM challenge outerchallenge 
    LEFT JOIN ( 
        SELECT teamID, challengeID, standardValueSum, standardUnit, FIND_IN_SET(standardValueSum, scores ) AS rank 
        FROM ( 
            SELECT teammember.teamID, mc.challengeID, sum(v.standardValue) standardValueSum, v.standardUnit 
            FROM v_activitystats v 
                INNER JOIN memberchallenge mc ON v.memberID = mc.memberID AND v.standardValue > 0 
                INNER JOIN teammember ON v.memberID = teammember.memberID 
                INNER JOIN challenge c ON mc.challengeID = c.challengeID 
                INNER JOIN challengeactivitytype cat ON c.challengeID = cat.challengeID AND cat.activityTypeID = v.activityTypeID 
            WHERE v.activityDate BETWEEN c.startDate AND c.endDate 
                AND c.challengeID = 33  
            GROUP BY standardUnit, challengeID, teamID 
            ) vstats 
    CROSS JOIN ( 
        SELECT GROUP_CONCAT( DISTINCT standardValueSum ORDER BY standardValueSum DESC ) AS scores 
        FROM ( 
            SELECT teammember.teamID, mc.challengeID, sum(v.standardValue) standardValueSum 
            FROM v_activitystats v 
                INNER JOIN memberchallenge mc ON v.memberID = mc.memberID AND v.standardValue > 0 
                INNER JOIN teammember ON v.memberID = teammember.memberID 
                INNER JOIN challenge c ON mc.challengeID = c.challengeID 
                INNER JOIN challengeactivitytype cat ON c.challengeID = cat.challengeID AND cat.activityTypeID = v.activityTypeID 
            WHERE v.activityDate BETWEEN c.startDate AND c.endDate 
                AND c.challengeID = 33  
            GROUP BY challengeID, teamID 
            ) vstats 
        ) scores 
    ) scoring 

    ON outerchallenge.challengeID = scoring.challengeID 
        INNER JOIN team t ON scoring.teamID = t.teamID 

Вот форматированный запрос: http://mysql.pastebin.com/XggRL5kX

ChallengeID, Team, Ranking 99Red Team 1 99 Blue Team 2

Еще раз, это прекрасно работает для конкретной задачи, (ID = 33)

Я хочу получить запрос с таким же рейтингом, нодля нескольких задач, например, тех, которые уже закончились.

Я пробовал этот запрос:

SELECT rankings.teamID, stuff.teamName, rankings.challengeID, 
        rankings.ChallengeName, rankings.ChallengeDescription, rankings.startDate, rankings.endDate, 
        rankings.standardValueSum, rankings.standardUnit, rankings.rank 
FROM challenge chal 
    LEFT JOIN ( 
    SELECT t.teamID, t.teamName, scoring.challengeID, 
        outerchallenge.name AS ChallengeName, outerchallenge.description AS ChallengeDescription, outerchallenge.startDate, outerchallenge.endDate, 
        scoring.standardValueSum, scoring.standardUnit, scoring.rank 
    FROM challenge outerchallenge 
        LEFT JOIN ( 
            SELECT teamID, challengeID, standardValueSum, standardUnit, FIND_IN_SET(standardValueSum, scores ) AS rank 
            FROM ( 
                SELECT teammember.teamID, mc.challengeID, sum(v.standardValue) standardValueSum, v.standardUnit 
                FROM v_activitystats v 
                    INNER JOIN memberchallenge mc ON v.memberID = mc.memberID AND v.standardValue > 0 
                    INNER JOIN teammember ON v.memberID = teammember.memberID 
                    INNER JOIN challenge c ON mc.challengeID = c.challengeID 
                    INNER JOIN challengeactivitytype cat ON c.challengeID = cat.challengeID AND cat.activityTypeID = v.activityTypeID 
                WHERE v.activityDate BETWEEN c.startDate AND c.endDate 
                GROUP BY standardUnit, challengeID, teamID ) vstats 
            CROSS JOIN ( 
                SELECT GROUP_CONCAT( DISTINCT standardValueSum ORDER BY standardValueSum DESC ) AS scores 
                FROM ( 
                    SELECT teammember.teamID, mc.challengeID, sum(v.standardValue) standardValueSum 
                    FROM v_activitystats v 
                        INNER JOIN memberchallenge mc ON v.memberID = mc.memberID AND v.standardValue > 0 
                        INNER JOIN teammember ON v.memberID = teammember.memberID 
                        INNER JOIN challenge c ON mc.challengeID = c.challengeID 
                        INNER JOIN challengeactivitytype cat ON c.challengeID = cat.challengeID AND cat.activityTypeID = v.activityTypeID 
                    WHERE v.activityDate BETWEEN c.startDate AND c.endDate 
                    GROUP BY challengeID, teamID 
                ) vstats 
            ) scores 
        ) scoring ON outerchallenge.challengeID = scoring.challengeID 
        INNER JOIN team t ON scoring.teamID = t.teamID 
) rankings ON chal.challengeID = rankings.challengeID
WHERE chal.endDate <= current_date()

Вот отформатированный запрос: http://mysql.pastebin.com/mSZwtDm3

Но вместо каждогоВызов, занявший 1-е место и 2-е место, занял место в рейтинге всех задач.Вот так

ChallengeID, команда, рейтинг 99 Красная команда 1 99 Синяя команда 2 134 Красная команда 3 134 Синяя команда 4 443 Красная команда 5 442 Синяя команда 6

Итак, я полагаю,Я оцениваю рейтинг не в том месте, но у меня нет идей, как заставить эту работу работать.Как я могу получить такие результаты: ChallengeID, команда, рейтинг 99 Красная команда 1 99 Синяя команда 2 134 Красная команда 1 134 Синяя команда 2 443 Красная команда 1 443 Синяя команда 2

1 Ответ

0 голосов
/ 05 августа 2010

Похоже, что вы ищете, это предложение Oracle "PARTITION BY", которое подгруппировало бы и затем позволяло бы вам ранжироваться несколько раз, как вы пытаетесь сделать.

Вероятно, самый простой способ обойти этовместо того, чтобы пытаться отобразить рейтинг, сгенерированный mySQL, вы можете создать свой собственный.

Вот лучший пример, чем я мог бы сформулировать, эй, это почти 4 часа утра !
http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/

...