SQL获取指定用户获胜的民意调查

时间:2010-06-23 11:42:28

标签: mysql sql count

大家好,并提前致谢 我有表accountsvotescontests
投票由作者ID,胜利者ID和比赛ID组成,以阻止人们投票两次 我喜欢为任何特定帐户显示,他们赢了多少次比赛,他们获得了多少次第二次以及他们获得了多少次第三次 什么是最快(执行时间)的方式来做到这一点? (我正在使用MySQL)

2 个答案:

答案 0 :(得分:1)

在使用MySQL很长一段时间后,我得出的结论是,几乎任何GROUP BY的使用对性能都非常不利,所以这里有一个带有几个临时表的解决方案。

CREATE TEMPORARY TABLE VoteCounts (
  accountid INT,
  contestid INT,
  votecount INT DEFAULT 0
);

INSERT INTO VoteCounts (accountid, contestid)
  SELECT DISTINCT v2.accountid, v2.contestid
  FROM votes v1 JOIN votes v2 USING (contestid)
  WHERE v1.accountid = ?; -- the given account

确保您在votes(accountid, contestid)上有索引。

现在,您有一个表格,其中列出了您的指定用户所参加的所有比赛,以及所有其他参加同一比赛的比赛。

UPDATE Votes AS v JOIN VoteCounts AS vc USING (accountid, contestid)
SET vc.votecount = vc.votecount+1;

现在,每个比赛的每个帐户都有投票数。

CREATE TEMPORARY TABLE Placings (
  accountid INT,
  contestid INT,
  placing INT
);

SET @prevcontest := 0;
SET @placing := 0;
INSERT INTO Placings (accountid, placing, contestid)
  SELECT accountid, 
    IF(contestid=@prevcontest, @placing:=@placing+1, @placing:=1) AS placing,
    @prevcontest:=contestid AS contestid
  FROM VoteCounts
  ORDER BY contestid, votecount DESC;

现在,您有一张桌子,每个帐户与每个比赛中各自的位置配对。获得给定位置的计数很容易:

SELECT accountid, COUNT(*) AS count_first_place
FROM Placings
WHERE accountid = ? AND placing = 1;

你可以使用MySQL技巧在一个查询中完成所有三个操作。布尔表达式总是在MySQL中返回一个整数值0或1,因此您可以使用SUM()来计算1的值。

SELECT accountid, 
  SUM(placing=1) AS count_first_place,
  SUM(placing=2) AS count_second_place,
  SUM(placing=3) AS count_third_place
FROM Placings
WHERE accountid = ?; -- the given account

重新评论:

是的,无论从标准化数据到您想要的结果,这都是一项复杂的任务。您希望它再次聚合(求和),排名和聚合(计数)。这是一堆工作! : - )

此外,单个查询并不总是执行给定任务的最快方法。程序员常常误解,较短的代码隐含着更快的代码。

注意我没有对此进行测试,因此您的里程可能会有所不同。


重新提出有关更新的问题:

在不使用GROUP BY的情况下,每个帐户获得COUNT()个投票是一种棘手的方法。我已经添加了表别名v和vc,所以现在可能会更清楚了。在votes表中,给定帐户/竞赛有N行。在votescount表格中,每个帐户/竞赛都有一行。当我加入时,UPDATE将根据N行进行评估,因此如果我为这N行中的每一行添加1,我会在与votescount相对应的每个相应帐户/竞赛的行中得到N的计数。< / p>

答案 1 :(得分:0)

如果我正确地解释事情,要阻止人们投票两次,我认为你只需要作者(账户?)ID和contestID在投票表上有一个唯一索引。它不会阻止人们拥有多个帐户并进行两次投票,但这会阻止任何人在同一帐户中两次投票。为了防止欺诈(袜子傀儡帐户),您需要检查投票模式,并检测帐户何时更频繁地为另一个帐户投票,然后才能进行统计。除非你有很多可能真的很难的比赛。