2010-06-23 54 views
1

您好所有,并在此先感谢 我有表accountsvotescontests
一票由一个作者ID,赢家ID,和比赛的ID,以便停止人们投票两次
编号喜欢为任何给定的帐户显示,多少次他们赢得了比赛,多少次他们第二次和多少次他们来第三
什么是最快(执行时间)的方式来做到这一点? (即时通讯使用MySQL)SQL获取指定的用户投票中获胜

+0

您应该添加3个表格的确切方案。这样可以更轻松地帮助完成所需的查询。例如,不清楚获胜者是否保存在比赛表中,或者只能由选票决定。 – 2010-06-23 11:58:27

+0

我可能会考虑将获胜者存储在“比赛”表中并定期更新,但现在我只想知道用户是第一,第二和第三次(纯粹通过计票)确定的次数 – Pez 2010-06-23 12:39:00

回答

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([email protected], @placing:[email protected]+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 

回复您的评论:

是的,这是一个复杂的任务,无论从你你想要的结果的归一化数据去的地方。您希望将其汇总(汇总),排名并再次汇总(计数)。这是一堆工作! :-)

此外,单个查询并不总是执行给定任务的最快方式。在程序员中,一个常见的误解是,较短的代码隐式地加快了代码的速度。

注意我没有测试过,所以你的里程可能会有所不同。


重新您有关更新的问题:

这让每个帐户票COUNT()没有使用GROUP BY的一个取巧的方法。我已经添加了表别名v和vc,所以现在可能会更清楚。在votes表中,给定帐户/比赛有N行。在votescount表中,每个帐户/比赛有一行。当我加入时,UPDATE是针对N行进行评估的,所以如果我为这N行中的每一行加1,那么我在每个相应帐户/竞赛对应的行中获得存储在votescount中的N的计数。

+0

所以我正确地认为这将是相当密集现在问题我怎么做,没有办法做到这一点在一个单一的查询?或者你认为这是最快的方法吗?再次感谢btw – Pez 2010-06-23 12:56:10

+0

干杯的人,它完美的作品,虽然我不明白的语法,到底是什么这样做: '更新投票加入投票计算使用(accountid,contestid) SET votecount = votecount + 1;' 这是否设置投票计数从表'投票'的表决计数fromo表'VoteCounts'?我注意到'投票'没有再次被引用,所以我把这两行出来了,它似乎工作得很好,没有它 – Pez 2010-06-23 14:43:45

0

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

+0

是啊我已经让他们索引的作者和比赛谢谢:)对帐单的巨大感激,生病尝试在一秒内出 – Pez 2010-06-23 12:25:05