2012-05-03 5 views
0

Немного информации о предыстории; это приложение, которое позволяет пользователям создавать проблемы, а затем голосует по этим вызовам (стандартное приложение типа userX-vs-userY).Внесение вложенных запросов MySQL

Конечная цель состоит в том, чтобы получить список из 5 пользователей, отсортированных по количеству проблем, которые они выиграли, чтобы создать тип таблицы лидеров. Задача выигрывает пользователь, если он имеет статус = истек, и у пользователя есть 50 голосов за этот вызов (задачи истекают после 100 голосов в общей сложности).

Я немного упрощает здесь, но, по существу есть три таблицы:

  1. пользователи

    • идентификатор
    • имя пользователя
    • ...
  2. Задачи

    • ID
    • issued_to
    • issued_by
    • статус
  3. challenges_votes

    • ид
    • challenge_id
    • user_id
    • voted_for

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

SELECT `challenges`.`id` 
FROM `challenges_votes` 
LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`) 
WHERE `voted_for` = 1 
WHERE `challenges`.`status` = 'expired' 
GROUP BY `challenges`.`id` 
HAVING COUNT(`challenges_votes`.`id`) > 50 

Что в этом примере будет возвращать идентификаторы вызов с истекшим сроком годности и когда пользователь с ID 1 имеет> 50 голосов.

Что мне нужно сделать, это подсчитать количество строк, возвращаемых здесь, применить его к каждому пользователю из таблицы пользователей, заказывал по количеству возвращаемых строк и ограничить его до 5.

С этой целью я имеют следующий запрос:

SELECT `users`.`id`, `users`.`username`, COUNT(*) AS challenges_won 
FROM (
    SELECT `challenges`.`id` 
    FROM `challenges_votes` 
    LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`) 
    WHERE `voted_for` = 1 
    GROUP BY `challenges`.`id` 
    HAVING COUNT(`challenges_votes`.`id`) > 0 
) AS challenges_won, `users` 
GROUP BY `users`.`id` 
ORDER BY challenges_won 
LIMIT 5 

который является своим родом получает там, но, конечно, voted_for идентификатор пользователя здесь всегда 1. является ли это даже правильный путь идти об этом типе запроса? Может ли кто-нибудь пролить свет на то, как я должен это делать?

Спасибо!

+0

Привет, не могли бы вы предоставить более подробную информацию о вашей структуре таблицы? Я думал, что 'challenge_votes' будет иметь user_id, но я не могу найти его в вашем запросе. –

+0

Столбец voted_for в 'challenge_votes' - это идентификатор пользователя, для которого предназначен голос, тогда как user_id - это идентификатор пользователя, который сам поместил голосование (что не актуально в этом запросе). – paulbennett

ответ

3

Я предполагаю следующий сценарий будет решить вашу проблему:

-- get the number of chalenges won by each user and return top 5 
SELECT usr.id, usr.username, COUNT(*) AS challenges_won 
FROM users usr 
JOIN (
    SELECT vot.challenge_id, vot.voted_for 
    FROM challenges_votes vot 
    WHERE vot.challenge_id IN (  -- is this check really necessary? 
     SELECT cha.id     -- if any user is voted 51 he wins, so 
     FROM challenges cha   -- why wait another 49 votes that won't 
     WHERE cha.status = 'expired' -- change the result? 
    )         -- 
    GROUP BY vot.challenge_id 
    HAVING COUNT(*) > 50 
) aux ON (aux.voted_for = usr.id) 
GROUP BY usr.id, usr.username 
ORDER BY achallenges_won DESC LIMIT 5; 

Пожалуйста, позвольте мне предложить небольшое рассмотрение в состоянии закрыть проблему: если пользователь выигрывает после 51 голосов, почему это необходимо подождать еще 49 голосов, которые не изменят результат? Если это ограничение можно отбросить, вам не нужно будет проверять таблицу challenges, и это может улучшить производительность запросов - но, это может ухудшиться, вы можете сказать только после тестирования с вашей фактической базой данных.

+0

Perfect - спасибо! Мы оставляем проблемы открытыми, пока не достигнем 100 голосов, чтобы в какой-то момент мы могли подсчитать общее количество голосов для пользователя (где у пользователя может быть до 100 голосов за вызов). – paulbennett

Смежные вопросы