2010-11-18 9 views
4

私はvotesという名前のデータベーステーブルを 'timestamp'、 'voter'、および 'voted_for'の3つの列に持っています。MySQLでどのように投票しますか?

表の各エントリは1票を表します。私はいくつかの条件で、それぞれの「voted_for」のすべての投票を集計したいと思います。

次のような条件は以下のとおりです。

  • 各有権者は、単一の有権者によって複数の投票の場合、最も最近の投票数では、一度だけ投票することができます。

  • 指定時間前に行われた投票のみがカウントされます。

+0

あなたの基準は完全な意味がありません。どのように投票を集計したいですか?あなたは簡単なカウントをしていますか?それが単なる数であれば、投票者を一度カウントするのではなく、なぜ最新の投票者が必要なのかは理解できません。 –

+0

@アリソン:私が理解しているように、ユーザーが投票を変更した可能性があるので、OPは最後に投票したものを取得したいと考えています。 @ジョーンブリットン:新しい行を作成するのではなく、ユーザーが投票を更新したときに同じ行を再利用するだけの理由はありますか?そうすれば、ユーザーの投票は常に最新のものになります。 –

+0

@musicfreak、あなたは正しいです。私は行を更新することができたかもしれませんが、簡単にするために、私はすべての投票を記録しました。誰が投票を変更したのかを見ることができるのは面白いと思った。 – johndbritton

答えて

4

はこれを試してみてください。

SELECT voted_for, count(*) 
FROM votes v 
INNER JOIN (SELECT Voter, Max(timestamp) as lastTime from votes group by Voter) A 
on A.Voter = v.voter and a.lasttime = v.timestamp 
WHERE timestamp < {date and time of last vote allowed} 
Group by voted_for 
+0

ありがとうございます、私はエラー "#1054 - 不明な列 'a.lasttime' 'on節'を取得していますが、これは右のように見えます。 – johndbritton

+0

エイリアスがAで、a.lasttimeが小文字である可能性があります...私はいつもMySQLの大文字小文字の区別について忘れています! – Leslie

0
SELECT voted_for,COUNT(DISTINCT voter) 
FROM votes 
WHERE timestamp < '2010-11-18 21:05:00' 
GROUP BY voted_for 
+0

それは近いですが、私はそれが完全に正しいとは思わない。この問合せでは、複数回投票された有権者による最新の投票を確実にカウントする必要があります。あなたの質問は、各有権者の投票を1つだけカウントするようにしますが、それが最新の投票であることを確認しません。 – johndbritton

+2

2回以上投票するユーザーがデータベースの行数を減らすために2番目のエントリを作成するのではなく、既存の投票を上書きするだけの理由はありませんか? – Webnet

+0

これは、すべての投票者が投票した投票者ではなく、すべての投票者をカウントします。 – Leslie

0

以下が役に立つことを証明可能性があります

drop table if exists users; 
create table users 
( 
user_id int unsigned not null auto_increment primary key, 
username varbinary(32) not null, 
unique key users_username_idx(username) 
)engine=innodb; 

insert into users (username) values 
('f00'),('foo'),('bar'),('bAr'),('bish'),('bash'),('bosh'); 

drop table if exists picture; 
create table picture 
( 
picture_id int unsigned not null auto_increment primary key, 
user_id int unsigned not null, -- owner of the picture, the user who uploaded it 
tot_votes int unsigned not null default 0, -- total number of votes 
tot_rating int unsigned not null default 0, -- accumulative ratings 
avg_rating decimal(5,2) not null default 0, -- tot_rating/tot_votes 
key picture_user_idx(user_id) 
)engine=innodb; 

insert into picture (user_id) values 
(1),(2),(3),(4),(5),(6),(7),(1),(1),(2),(3),(6),(7),(7),(5); 


drop table if exists picture_vote; 
create table picture_vote 
( 
picture_id int unsigned not null, 
user_id int unsigned not null,-- voter 
rating tinyint unsigned not null default 0, -- rating 0 to 5 
primary key (picture_id, user_id) 
)engine=innodb; 

delimiter # 

create trigger picture_vote_before_ins_trig before insert on picture_vote 
for each row 
proc_main:begin 

declare total_rating int unsigned default 0; 
declare total_votes int unsigned default 0; 

if exists (select 1 from picture_vote where 
    picture_id = new.picture_id and user_id = new.user_id) then 
     leave proc_main; 
end if; 

select tot_rating + new.rating, tot_votes + 1 into total_rating, total_votes 
    from picture where picture_id = new.picture_id; 

-- counts/stats 
update picture set 
    tot_votes = total_votes, 
    tot_rating = total_rating, 
    avg_rating = total_rating/total_votes 
where picture_id = new.picture_id; 

end proc_main # 

delimiter ; 

insert into picture_vote (picture_id, user_id, rating) values 
(1,1,5),(1,2,3),(1,3,3),(1,4,2),(1,5,1), 
(2,1,1),(2,2,2),(2,3,3),(2,4,4),(2,5,5),(2,6,1),(2,7,2), 
(3,1,5),(3,2,5),(3,3,5),(3,4,5),(3,5,5),(3,6,5),(3,7,5); 

select * from users order by user_id; 
select * from picture order by picture_id; 
select * from picture_vote order by picture_id, user_id; 
+2

私はこれが別の質問に答えると思われたと思います... – Leslie

+0

あなたはhmmmm select countと同じようにトリガとタリーを使用します。inner join ... 1,000万行後 - –

+0

私はそれが最高の答えだとは思わないので、私はこれを投票するつもりはありません。しかし、確かに、質問者が望んでいることを行うために、違った、完全に有効な方法を提示するという観点からは、間違いなく役立ちます。 –

関連する問題