简体   繁体   中英

SQL sum hits per day and calculate percentage change

I have a single table with a list of hits/downloads, every row has of course a date. I was able to sum all the rows grouped by day.

Do you think it's possible to also calculate the change in percentage of every daily sum compared to the previous day using a single query, starting from the entire list of hits?

I tried to do this

select *, temp1.a-temp2.b/temp1.a*100 as percentage from
(select DATE(date), count(id_update) as a from vas_updates group by DATE(date)) as table1
 UNION
(select DATE_ADD(date, INTERVAL 1 DAY), count(id_update) as b from vas_updates group by DATE(date)) as table2, vas_updates

but it won't work (100% CPU + crash). Of course I can't JOIN them because those two temp tables share nothing in common being with 1 day offset.

The table looks like this, nothing fancy.

id_updates | date
1            2014-07-06 12:45:21
2            2014-07-06 12:46:10
3            2014-07-07 10:16:10

and I want

date       | sum a | sum b | percentage
2014-07-07   2       1       -50%

It can be either be positive or negative obviously

select DATE(v.date), count(v.id_update) a, q2.b, count(v.id_update) - q2.b/count(v.id_update)*100 as Percentage
from vas_updates v
Left Join (select DATE_ADD(date, INTERVAL 1 DAY) d2, count(id_update) as b 
           from vas_updates group by d2) as q2
ON v.date = q2.d2
group by DATE(v.date)

The sum by day is:

select DATE(date), count(id_update) as a
from vas_update
group by DATE(date);

In MySQL, the easiest way to get the previous value is by using variables, which looks something like this:

select DATE(u.date), count(u.id_update) as cnt,
       @prevcnt as prevcnt, count(u.id_update) / @prevcnt * 100,
       @prevcnt := count(u.id_update)
from vas_update u cross join
     (select @prevcnt := 0) vars
group by DATE(u.date)
order by date(u.date);

This will generally work in practice, but MySQL doesn't guarantee the ordering of variables. A more guaranteed approach looks like:

select dt, cnt, prevcnt, (case when prevcnt > 0 then 100 * cnt / prevcnt end)
from (select DATE(u.date) as dt, count(u.id_update) as cnt,
             (case when (@tmp := @prevcnt) is null then null
                   when (@prevcnt := count(u.id_update)) is null then null
                   else @tmp
              end) as prevcnt
      from vas_update u cross join
           (select @prevcnt := 0, @tmp := 0) vars
      group by DATE(u.date)
      order by date(u.date)
     ) t;

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