MySQL查询:候选人赢了多少次选举?

时间:2012-03-31 01:25:15

标签: php mysql sql

我正在用PHP编写一个用于模拟选举的PHP的Web应用程序。

我有三张桌子:候选人,选举和投票。投票包含CandidateID,ElectionID和Count,它是给定候选人在给定选举中投票的次数。投票还包含TimeStamp,这是修改行的最后一次用于打破关系(早先的投票获胜)。候选人可能参加多次选举。我怎样才能找到一个候选人赢得多少次选举?

所有的帮助非常感谢,谢谢。

一些示例数据:

CREATE TABLE IF NOT EXISTS `Votes` (
`ElectionID` int(11) unsigned NOT NULL,
`CandidateID` int(11) unsigned NOT NULL,
`Count` smallint(5) unsigned NOT NULL DEFAULT '0',
`stamp` int(11) unsigned NOT NULL,
PRIMARY KEY (`ElectionID`,`CandidateID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `Votes` (`ElectionID`, `CandidateID`, `Count`, `stamp`) 
VALUES
(1, 1, 3, 1332897534),
(4, 1, 3, 1333149930),
(4, 4, 2, 1333149947),
(4, 5, 3, 1333149947),
(1, 4, 4, 1333153373);

所需的输出:一行,一列,是某个候选人的获胜次数

5 个答案:

答案 0 :(得分:2)

你可以写:

SELECT COUNT(1)
  FROM Elections AS e
 INNER
  JOIN Votes AS v1 -- representing the candidate of interest
    ON v1.ElectionID = e.ID
   AND v1.CandidateID = ...
  LEFT
 OUTER
  JOIN Votes AS v2 -- representing a candidate who beat the candidate of interest
    ON v2.ElectionID = e.ID
   AND (    v2.Count > v1.Count
         OR (     v2.Count = v1.Count
              AND v2.stamp < v1.stamp
            )
       )
 WHERE v2.ElectionID IS NULL -- meaning that no candidate beat the candidate of interest
;

(也可以使用EXISTS和相关子查询来表示其中一个或两个连接;或者可以使用不相关的子查询将第一个连接更改为IN;但以上是最多的可能表现最好,恕我直言,我在StackOverflow上的经验是因为某些原因人们似乎更喜欢加入子查询。如果你更喜欢子查询答案,请告诉我。)

答案 1 :(得分:0)

SELECT CandidateID, MAX(Count) FROM Votes GROUP BY ElectionID

应该做的伎俩

答案 2 :(得分:0)

您的查询基本上需要返回每次选举,并且世卫组织赢得了它。然后将该结果应用于您感兴趣的特定候选人,以了解该人在所有选举中获胜的人数。例如:在美国共和党竞选中,你有4个候选人...... 2真的是唯一真正考虑过的,无论党派如何。每个政党都在各个州开展竞选活动,并且各自都有各自的选票。所以,在前20个州的末尾,你只会有21位获胜者,但是谁赢了多少。候选人“A”可赢10分,“B”获胜6分,“C”获胜3分,“D”获胜2分。所以如果你想知道有多少候选人“B”获胜,你的答案是6 ...来自我对你问题的印象。

这将为您提供给定候选人的所有符合条件的“第一名”选举。如果您关心的只是HOW MANY,您只需将Prequery.fields更改为COUNT(*)即可。如果您想获得候选人的姓名和选举的名称/信息,您可以在执行PreQuery之后将其添加为连接条件。

select 
      PreQuery.idVotes,
      PreQuery.CandidateID,
      PreQuery.ElectionID,
      PreQuery.Votes,
      PreQuery.LastEntry
   from
      ( select
              v.*,
              @WinRow := if( @LastElection = v.ElectionID, @WinRow +1, 1 ) as FinalPlace,
              @LastElection := v.ElectionID as ignoreMe
           from
              Votes v,
              ( select @WinRow := 0, @LastElection := 0 ) sqlvars
           order by
              v.ElectionID,
              v.Votes DESC,
              v.LastEntry ASC ) PreQuery
   where
          PreQuery.FinalPlace = 1
      AND PreQuery.CandidateID = CandidateIDYouAreInterestedIn

答案 3 :(得分:0)

基本上你想要做的是按ElectionID对投票行进行分组,然后按照递减顺序排序,标记升序。这将为您提供有序投票行的结果集,每个选举的“获胜者”为每个组中的第一行。

接下来,您要在每个组中选择这些第一行并丢弃其余的行(请参阅此处了解如何进行前N个查询:http://www.sqlines.com/mysql/how-to/get_top_n_each_group)。

最后,您要从此结果集中选择count(*),其中CandidateID =您正在寻找的任何候选者。或者,您可以按CandidateID进行分组,如果您想要所有候选人的胜利次数而不是特定的候选人,则可以省略where子句。

希望这有帮助。

答案 4 :(得分:0)

显然我迟到了,但这是我的第一件事:

  1. 首先有一个子查询为投票中的每个唯一选举人选择获胜计数,请调用此表wins
  2. 然后,加入wins与选举和计数相等的投票。因为可能存在平局,我们还需要选择具有最低标记的投票行,因此我们将按比例和计数进行分组,但这次选择最小标记。我们会将此结果表wins_with_stamp / wws称为简短。
  3. 现在,wins_with_stamp拥有来自投票的所有“赢”行的行,因此选择特定候选人获胜的数量只是where candidateid = ?条款的问题。

    -- Returns how many Votes rows that is the winner of its election  
    -- and candidateid is the candidate in question
    select count(*)
    from Votes v2
    right join (
       -- Gets the earliest stamp for the votes with the winning count for each election
        select v.electionid, v.count, min(v.stamp) as minstamp
        from Votes v
        right join (
            -- Gets the winning count for each election
            select electionid, max(count) as max
            from Votes
            group by electionid
        ) wins on wins.max = v.count and wins.electionid = v.electionid
        group by electionid, count
    ) wws on wws.count = v2.count and wws.electionid = v2.electionid and wws.minstamp = v2.stamp
    where candidateid = [YOUR_CANDIDATEID]