简体   繁体   中英

mysql query: how to get the number of yes/no votes per day

I have to create a mysql query to get a voting distribution of each day exceeding a particular date, something like this...

    date          yes_votes    no_votes
------------------------------------------
    2010-01-07    21           22
    2010-01-07    2            0

My table is like this..

    post_votes
--------------------------
    id(longint)
    date(timestamp)
    flag(tinyint) // this stores the yes/no votes 1-yes, 2-no

I am stuck at this....

SELECT COUNT(*) AS count, DATE(date) FROM post_votes WHERE date > '2010-07-01' GROUP BY DATE(date)

this gives the total number of votes per day, but not the distribution that I want.

SELECT COUNT(*) AS count
     , DATE(date)
     , SUM(flag = 1) AS yes_votes
     , SUM(flag = 2) AS no_votes
FROM post_votes 
WHERE date > '2010-07-01' 
GROUP BY DATE(date)

This is a trick that works in MySQL, as flag=1 will either be True or False . But True = 1 and False = 0 in MySQL so you can add the 1s and 0s using the SUM() function.

Other solutions with IF or CASE would be better for clarity or if there is any chance you want to move the database to another RDBMS.

Comments not related to the question:

  • It's bad habit to use reserved words like date or count for naming fields or tables.
  • It's also not good to use "date" when you actually store a timestamp. Names should reflect use.
  • For table names it's recommended to use singular ( post_vote ) and not plural - although many use plural, it gets confusing in the end. Plural is good for some fields or calulated fields, like your yes_votes and no_votes where we have a counting.

Sum it:

select date(date) as date,
       sum(case when flag = 1 then 1 else 0) as yes,
       sum(case when flag = 2 then 1 else 0) as no
from post_votes
where date > '2010-07-01'
group by date(date)

you are almost at the solution:)

i would recommend the use of an IF condition in a SUM method like so:

SELECT SUM(IF(flag = 'yes',1,0)) AS yes_count,
       SUM(IF(flag = 'no',1,0)) AS no_count, 
       DATE(date) 
FROM post_votes 
WHERE date > '2010-07-01' 
GROUP BY DATE(date)

this will allow for the function to add 1 to each sum only if the value is equal to yes / no

SELECT DATE(date) as dt,
sum(if(flag=1,1,0)) as yes,
sum(if(flag=2,1,0)) as no
FROM post_votes WHERE date > '2010-07-01' 
GROUP BY dt

I had that problem too. The best solution of that I can think of, is to split the "flag" in two fields, like:

upvote(tinyint)
downvote(tinyint)

Then you are able to count them very easy and without mysql-voodoo:

SELECT 
  SUM(upvote) AS up,
  SUM(downvote) AS down,
  DATE(`date`) AS Created_at
FROM post_votes 
WHERE Created_at > '2010-07-01' 
GROUP BY Created_at

Btw.: You should not name a column date , because it's a MySQL-Keyword.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM