views:

243

answers:

2

Hello,

I have a table which looks like this:

ID   Date      Size   Marked
1    2010-02-02    2        X
2    2002-02-02    1
1    2010-02-03    2        X
2    2010-02-03    3        
3    2010-02-03    4        X

And I have a code (PHP) which does following things: a) Calculate sum of sizes per day b) Find the difference between total for this day and last day. c) Find the sum of sizes for rows which became marked this day (the row with the same id wasn't marked yesterday).

As example, I will get following results:

Date        Total  DiffWithYesterday  MarkedThisDay
2010-02-02    3      0                  0
2010-02-03    9      6                  4

I have feeling that there is a way to write this in SQL. However I am quite weak in SQL, so I gave up after a day playing around inner joins, group by and embedded selects.

I would appreciate, if you give me some clues how to do that.

Oh.. And I am using MySQL.

Regards, Victor

+1  A: 

Something like this works in SQL Server. I don't have MySQL to test but you can probably convert once you see the logic.

create table so (sodate datetime, sosize int, somarked varchar(1))

insert into so (sodate,sosize,somarked) values ('1-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('2-jan-2010',1,'X')
insert into so (sodate,sosize,somarked) values ('3-jan-2010',2,'X')
insert into so (sodate,sosize,somarked) values ('4-jan-2010',0,null)
insert into so (sodate,sosize,somarked) values ('5-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',1,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',4,null)
insert into so (sodate,sosize,somarked) values ('6-jan-2010',1,null)
insert into so (sodate,sosize,somarked) values ('7-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('8-jan-2010',3,'X')
insert into so (sodate,sosize,somarked) values ('9-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('10-jan-2010',2,'X')
insert into so (sodate,sosize,somarked) values ('11-jan-2010',1,'X')
insert into so (sodate,sosize,somarked) values ('12-jan-2010',2,null)
insert into so (sodate,sosize,somarked) values ('13-jan-2010',3,'X')

select so.sodate
    ,sum(so.sosize) as Total
    ,isnull(sum(so.sosize),0) - isnull(min(so2.sosize),0) as DiffFromYesterday
    ,sum(case when so.somarked = 'X' then so.sosize end) as MarkedThisDay
from so
    left join (select so.sodate,sum(so.sosize) sosize from so group by sodate) so2 on dateadd(dd,1,so2.sodate) = so.sodate
group by so.sodate  

..and after installing mysql this seems to work there...

select so.sodate
    ,sum(so.sosize) as Total
    ,ifnull(sum(so.sosize),0) - ifnull(min(so2.sosize),0) as DiffFromYesterday
    ,sum(case when so.somarked = 'X' then so.sosize end) as MarkedThisDay
from so
    left join (select so.sodate,sum(so.sosize) sosize from so group by sodate) so2 on (so2.sodate + INTERVAL 1 day )= so.sodate
group by so.sodate  ;
Craig
Thank you. That worked like a charm :) I was able to figure out how to adopt it to MySQL, when I saw the first answer.
Victor Ronin
+1  A: 

had fun with this one.

SELECT 
  today.date as Date, 
  today.total as Total, 
  (today.total - yesterday.total) as DiffWithYesterday  , 
  marked.total as MarkedThisDay
FROM
  (SELECT date, sum(size) as total
   FROM table_name
   GROUP BY date) today
LEFT JOIN 
  (SELECT date, sum(size) as total
   FROM table_name
   WHERE marked = 'X'
   GROUP BY date) marked ON today.date = marked.date
LEFT JOIN
  (SELECT (date + INTERVAL 1 day) as date, sum(size) as total
   FROM table_name
   GROUP BY date) yesterday ON today.date=yesterday.date

obviously, you will need to replace "table_name" with the name of your table

Bingy