Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CodeIgniter SQL query - how to sum values for each month?

I have the following table:

//table_1

record_id   user_id    plant_id    date        cost
1           1          1           2011-03-01   10
2           1          1           2011-03-02   10
3           1          1           2011-04-10   5
4           1          2           2011-04-15   5

I would like to build a query (if possible using CI Active Records, but MySQL is fine) in which I generate the following result:

[1] => [1] => [March 2011] [20]

           => [April 2011] [5]

       [2] => [March 2011] [0]

           => [April 2011] [5]

I have tried using $this->db->group_by but I think I'm not using it correctly.

If anyone could give me a pointer or roadmap to get this done it would be much appreciated -- thanks!

like image 661
pepe Avatar asked Dec 07 '25 09:12

pepe


2 Answers

Sample table

drop table if exists t;
create table t( record_id int, user_id int, plant_id int, date datetime, cost float);
insert t select
1 ,1, 1 ,'2011-03-01', 10 union all select
2 ,1, 1 ,'2011-03-02', 10 union all select
3 ,1, 1 ,'2011-04-10', 5 union all select
4 ,1, 2 ,'2011-04-15', 5;

Because you want to see the row with 0, you need to do a cross join between the year-month and all user-plants.

select up.user_id, up.plant_id, ym2, ifnull(sum(t.cost),0) totalcost
from (select distinct date_format(date, '%Y-%m') ym, date_format(date, '%M %Y') ym2 from t) dates
cross join (select distinct t.user_id, t.plant_id from t) up
left join t on date_format(t.date, '%Y-%m') = dates.ym
           and up.user_id=t.user_id
            and up.plant_id=t.plant_id
group by up.user_id, up.plant_id, ym2, ym
order by up.user_id, up.plant_id, date(concat(ym,'-1'));

The fact that Month Year does not sort correctly also requires the complex treatment of the dates for ordering purposes at the end.

like image 66
RichardTheKiwi Avatar answered Dec 09 '25 23:12

RichardTheKiwi


This is a pretty intense way to do it and it would be far preferable to store the month-year as a column itself if you need to make these queries frequently, but this is basically how it works:

SELECT CONCAT(MONTHNAME(date), ' ', YEAR(date)) AS monthyear, COUNT(*) AS count GROUP BY YEAR(date), MONTH(date), plant_id;

That should get you the resultset you're looking for.

like image 24
Michael McTiernan Avatar answered Dec 10 '25 00:12

Michael McTiernan