2010-06-23 46 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