2009-09-25 4 views
1

У меня есть таблица со следующими полями: id, opp1, opp2, opp1_votes, opp2_votes.MySQL: Как получить пользователя с наибольшим выигрышем?

Если у одного из кандидатов больше голосов, чем у другого, мы считаем, что он выиграл. Как я могу получить opp с большинством побед из этой таблицы?

+0

Ваш вопрос странный. Мы привыкли иметь таблицу типа (id, opp, opp_votes) и находить max. Почему столбцы дублируются? – KLE

+0

, вероятно, потому, что есть два противника друг против друга, которые он хранит. – Evernoob

+0

Я полагаю, что это система избирательного голосования – Glenner003

ответ

4

Этот запрос будет найти количество выигрышей для каждого пользователя, и порядок их в порядке убывания (так что одна с большинством побед будет первый ряд):

SELECT winner, COUNT(*) 
FROM 
    (
    SELECT opp1 AS winner FROM table 
    WHERE opp1_votes > opp2_votes 
    UNION ALL 
    SELECT opp2 AS winner FROM table 
    WHERE opp2_votes > opp1_votes 
    ) 
GROUP BY winner 
ORDER BY COUNT(*) DESC 

объяснение запрос:

  1. Сначала мы найдем все строки, для которых opp1 был победителем. Мы создаем таблицу, в которой победители opp1 перечислены под названием «победитель».
  2. Мы делаем то же самое, что и в (1), но теперь для случаев, когда opp2 был победителем.
  3. Мы объединяем два стола и получаем список всех победителей во всех играх.
  4. Теперь мы группируем итоговую таблицу по идентификатору победителя и выбираем счет из этой группы, в результате получаем список победителей, а для каждого - количество выигранных очков.
  5. Последнее звено с кодами по количеству побед.

Примечания:

  • В соответствии с выше запроса, если есть связь - нет победителя. Если вы хотите рассматривать связь как выигрыш для одного из пользователей, вам нужно определить эвристику тай-брейка.
  • Если вам действительно нужен только один результат, вы можете начать с SELECT TOP 1 winner, ... или закончите с LIMIT 1, но, насколько я знаю, он не сохранит время вычисления в общем случае, поэтому я его оставлю.
+0

В предложении ORDER BY отсутствует слово «BY»;) – Evernoob

+0

@Evernoob: исправлено, спасибо :) –

+0

, когда opp является победителем как opp1, а также как opp2, UNION стирает его, когда он фильтрует дубликаты. Я думаю, вы должны поставить «UNION ALL» – manji

0
SELECT opp, sum(win) wins FROM ( 
    SELECT opp1 opp, CASE WHEN opp1_votes > opp2_votes THEN 1 ELSE 0 END win 
     FROM otable 
    UNION ALL 
    SELECT opp2 opp, CASE WHEN opp2_votes > opp1_votes THEN 1 ELSE 0 END win 
     FROM otable 
) A 
GROUP BY opp 
ORDER BY sum(win) DESC LIMIT 1 
+0

Не уверен, что это возможно для конкретной конкретной базы данных, но этот подход может потерпеть неудачу, если один и тот же противник может появиться в opp1 для некоторых строк и opp2 в других строках. –

+0

Я думаю, что у вас есть проблема с круглыми скобками в линиях SUM. –

+0

@jbourque - все в порядке, вы просто хотите удостовериться, что для каждой строки вы либо возвращаете ее в первом случае (opp1 выигрывает), либо второй случай (opp2 выигрывает). Вы не сможете сказать после СОЮЗА, на котором позиционирует победитель. –

-2

Это делает то, что вы хотите?

select top 1 opp1, 
    (select count(*) 
     from table i 
     where i.opp1 = o.opp1 and i.opp1votes > i.opp2votes) as wins 
from table o 
order desc by wins 
+0

нет необходимости проверять opp2, потому что я предполагаю, что есть зеркальная запись в другом месте таблицы? иначе я не полностью понимаю ваш набор данных – dharga

+0

нисходящий ник не помогает никому – dharga

+0

Нет, вот как это работает: кто-то начинает битву, и он считается opp1, затем кто-то присоединяется к нему, а второй считается opp2 , Но каждый может начать или присоединиться к битве, поэтому один человек может быть opp1 или opp2 в разных случаях. – 2009-09-25 13:18:52

0
SELECT 
    CASE WHEN opp1_votes > opp2_votes THEN opp1 ELSE opp2 END as winner, 
    COUNT(*) 
FROM table 
GROUP BY CASE WHEN opp1_votes > opp2_votes THEN opp1 ELSE opp2 END 
ORDER BY COUNT(*) DESC 
+0

Спасибо за помощь. – 2009-09-25 13:44:00

0

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

SELECT 
(CASE WHEN `opp1_votes`>`opp2_votes` THEN `opp1` ELSE `opp2` END) `winner`, 
COUNT(*) AS `no_of_times` 
FROM `matches` 
GROUP BY `winner` 
ORDER BY `no_of_times` DESC 

То, что мы делаем здесь:

  1. сравнить, какой из них больше от opp1_votes и opp2_votes в разделе CASE WHEN
  2. Если opp1_votes выше, то мы выводим opp1 в winner колонках и наоборот
  3. Тогда группа результатов по победителю
  4. Теперь, если подсчитать количество строк, каждый победитель имеет мы получаем число побед каждого победителя
  5. в результаты отсортированы по no_of_times выиграл

Если вы хотите просто человек с наибольшим количеством побед вы можете добавить LIMIT 1 в конце запроса или вы можете обернуть выше запрос и выбрать максимум (no_of_times) от него как показано ниже:

SELECT `winner`, MAX(`no_of_times`) AS `no_of_times` FROM (
SELECT 
(CASE WHEN `opp1_votes`>`opp2_votes` THEN `opp1` ELSE `opp2` END) `winner`, 
COUNT(*) AS `no_of_times` 
FROM `matches` 
GROUP BY `winner` 
ORDER BY `no_of_times` DESC 
) AS `winners` 
+0

У меня уже есть соблазнение, но спасибо в любом случае – 2009-09-25 13:44:55

+0

Да, но это будет быстрее, но думаю, что это не всегда важно. Ну, мне понравилось это делать, так что не беспокойтесь – andho

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