2012-03-31 5 views
1

私は選挙をモデルにしたmySQLを使用してPHPでWebアプリケーションを作成しています。MySQL Query:候補者は選挙で何回勝利しましたか?

私は候補者、選挙、投票の3つのテーブルを持っています。投票には、候補者ID、ElectionID、およびカウントが含まれています。これは、指定された候補が、指定された選挙で投票された回数です。投票には、行が変更された最後の時刻であるタイムスタンプも含まれます。タイムスタンプは、ネクタイを破るために使用されます(以前の投票が勝ちました)。候補者は複数の選挙で動いている可能性があります。与えられた候補者が勝った選挙の数を確認するにはどうすればよいですか?

大変感謝しています。

いくつかのサンプルデータ:

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); 

所望の出力:1行、1列で、あること、特定の候補

+0

あなたは...興味のため – Teja

+0

@Vutukuriのおかげで、いくつかのサンプルデータと所望の出力を投稿することができます。上記の編集をご覧ください。 – user1304384

答えて

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に変更できます。上記のものがIMHOを最もよく実行する可能性が高く、StackOverflowに対する私の経験は、何らかの理由でサブクエリよりもジョインが好きであるように見えるということでした。サブクエリの回答を希望される場合は、私に教えてください)

+0

ありがとうございます。それは働いているようだ。 – user1304384

+0

@ user1304384:ようこそ! – ruakh

+0

また、あなたは非常に専門的なコード例です。 – user1304384

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

のための勝利数トリックを行う必要があります

+1

このクエリは、各選挙の勝利候補者の投票数を私に提供します。 – user1304384

+0

ああ、私は誤解しました。ほぼそこに。おそらくあなたは今簡単にCOUNT(CandidateID)/ COUNT(DISTINCT CandidateId)を使うことができますか?それが 'SELECT COUNT(CandidateID)FROM Votes GROUP BY ElectionID HAVING max(Count)'のようなものを使用するのであれば、またはORDER BY Count DESCを使用して最高位のみを取得します。私はあなたのためにそれをテストする時間がないので、少し周りにおもちゃをする必要があります。私はあなたが気にしないことを望む。 – ArendE

0

あなたの質問は、基本的にすべての選挙結果を返す必要があります。その結果を、あなたが興味を持っている特定の候補者に適用します。例:米国の共和党レースでは、4人の候補者があります... 2人は党所属に関係なく、ほとんどの人が考慮する唯一の実在者です。各党は各州でキャンペーンを実施し、それぞれの票が集計されます。だから、20の州の終わりには21人の勝者しかいないが、どれだけ勝ったのか。候補者 "A"が10、Bが6、Cが3、Dが2になります。候補者Bがどれくらいいるか知りたい場合は、6あなたの質問の印象。

これは、特定の候補者に対して、すべての適格「第1位」選挙を行います。あなたが気にかかっているのはどれだけ簡単なのか、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 
0

基本的にはあなたが何をしたいグループはElectionIDによる投票の行で、カウント下降、スタンプで昇順。それはあなたに各投票の行の結果セットを与え、各選挙の「勝者」を各グループ内の最初の行とします。

次に、各グループ内でこれらの最初の行を選択し、残りの部分を破棄します(http://www.sqlines.com/mysql/how-to/get_top_n_each_groupのTop-Nクエリの実行方法はここを参照)。

最後に、この結果セットから候補(候補)ID =候補を探したいとします。あるいは、候補者IDごとにグループ化し、特定の候補ではなくすべての候補者の勝ち数を求めたい場合は、where句を省略することができます。

これが役に立ちます。

0

どうやら私はパーティーに遅れてんだけど、これが最初の事Iのかかわらずです:

  1. まず、このテーブルwinsを呼び出して、投票の各ユニークelectionidのための勝利数を選択するための1つのサブクエリを持っています。
  2. 次に、winsに、electionidとcountが等しいVotesを結合します。ネクタイがある可能性があるので、最も低いスタンプのVotes行を選択する必要があります。したがって、electionidとcountでグループ化しますが、今回は最小スタンプを選択します。この結果の表を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] 
    
関連する問題