如何获得具有最大值的不同行

时间:2012-09-10 20:21:38

标签: mysql group-by distinct max

我很抱歉要问什么一定要解决这个问题很简单,但我似乎无法解决这个问题。我甚至无法想出一个非常适合我的问题的标题,请你赦免那也是。

我有一个民意调查,每个用户可以发布一个问题的多个答案,其他人则对这些答案进行投票。我需要得到一个结果,其中每个用户的最高投票回答都会被返回。

测试案例:让我们假设一个问题,例如“你最喜欢的歌曲是什么?”

CREATE TABLE `answers` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`authorId` INT,
`answer` TEXT NOT NULL ,
`votes` INT NOT NULL 
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO `answers` VALUES
(1, 30, "The West is the Best", 120),
(2, 30, "Come on, baby, light my fire", 100),
(3, 31, "Everything's gonna be allright", 350),
(4, 31, "Sayin' oooh, I love you", 350),
(5, 31, "Singing sweet songs of melodies pure and true", 290),
(6, 32, "I'm your pole and all you're wearing is your shoes", 540),
(7, 32, "And I'm crazier when I'm next to her", 180),
(8, 32, "You hear the music in the air", 230),
(9, 30, "You know they are a liar", 190)

我期望获得的结果是:

id | authorId | answer                                             | votes
 6 |       32 | I'm your pole and all you're wearing is your shoes | 540
 3 |       31 | Everything's gonna be allright                     | 350
 9 |       30 | You know they are a liar                           | 190

基本上我需要为每位作者选择最佳答案,然后按照最佳答案获得的投票对结果进行排序。同一作者的两个答案可能会有相同的票数;然后只应选择发布的第一个(较低的ID)(如答案#3和#4所示)。同一作者的两个不同答案可能永远不会出现在结果中 - 每个作者只能赢一次。

我已经搜索并搜索过并尝试过再次尝试,此刻我觉得自己被洗脑了......可能这在单个SQL查询中是不可行的;应该是这种情况,可能值得指出应用程序是用PHP编写的。我知道我可以使用ORDER BY votes desc, id asc获取所有答案,然后迭代结果,记住所有authorId并删除任何我已经看过authorId的行,但是我需要获得一定数量的记录,这可能会变得很尴尬(......如果我扔出太多行等,可能需要再次使用偏移量运行查询)..但最终它可能是最好的解决方案,如果单查询解决方案过于复杂或完全没有...

有什么想法吗? :O)

4 个答案:

答案 0 :(得分:5)

SELECT id, authorId, answer, votes
FROM (  SELECT id, authorId, answer, votes
        FROM answers
        ORDER BY votes DESC) AS h
GROUP BY authorId

这个小巧的技巧是基于GROUP BY构建的,以检索每个案例的第一行。通常这是默认ORDER BY id ASC,但通过此子查询,每个authorId中的第一行具有最高votes

注意:如Iain Elder所述,此解决方案不适用于ONLY_FULL_GROUP_BY活动,仅适用于MySQL。由于缺乏确认此行为的文档,此解决方案在某种程度上不受支持。它适用于我,但对我来说一直很好。

此方法仍适用于最新的MySQL on sqlfiddle

答案 1 :(得分:3)

您可以使用子选择:

select min(a1.id), a1.authorid, a2.mxvotes
from answers a1
inner join
(
  select authorid, max(votes) mxvotes
  from answers
  group by authorid
) a2
  on a1.authorid = a2.authorid
  and a1.votes = a2.mxvotes
group by a1.authorid, a2.mxvotes
order by mxvotes desc

请参阅SQL Fiddle with Demo

答案 2 :(得分:1)

很好的问题,Dan。

MySQL缺乏分析功能,使其易于解决。已向Oracle询问similar question,并使用带有MAX函数的OVER子句解决了该问题。这也适用于SQL Server。

您需要使用子查询在MySQL上执行此操作。这对我有用:

SELECT
  id,
  authorId,
  answer,
  votes
FROM answers AS firsts
WHERE id = (
  SELECT
    MIN(id)
  FROM answers AS favorites
  WHERE
    votes = (
      SELECT MAX(votes)
      FROM answers AS author_max
      WHERE author_max.authorId = favorites.authorID
    ) AND
    favorites.authorId = firsts.authorId 
)
ORDER BY votes DESC;

请参阅我的sqlfiddle以获取可执行示例。

答案 3 :(得分:0)

select * from (select * from answers order by votes desc) as temp group by authorId