简体   繁体   中英

Sum of values in Row in MySQL with condition

I have the following table. I want to sum the values present in rows by putting condition on dates.

Table - a
  ID   Entry_date     weight  height   ID1      start_date  end_date
 111   2001-03-31      43      187
 111   2001-04-30      23      165
 111   2001-05-31      34      172     111      2001-04-30  2001-05-31 
 112   2001-06-30      54      183
 112   2001-07-31      26      188     112      2001-06-30  2001-07-31
 113   2001-04-30      23      165
 113   2001-05-31      34      172     113      2001-04-30  2001-05-31 
 114   2001-05-31      46      177
 114   2001-06-30      54      183
 114   2001-07-31      26      188     114      2001-06-30  2001-07-31

If Entry_date >= start_date and Entry_date <= end_date then it should sum weight and height for those entry_dates and ID. I don't know if i explained it right way or not. Resulting table should be like this:

Table - 

      ID   Entry_date     weight  height   ID1      start_date  end_date
     111   2001-03-31      43      187    
     111   2001-05-31      57      337     111      2001-04-30  2001-05-31 
     112   2001-07-31      80      371     112      2001-06-30  2001-07-31 
     113   2001-05-31      57      337     113      2001-04-30  2001-05-31 
     114   2001-05-31      46      177
     114   2001-07-31      80      371     114      2001-06-30  2001-07-31

I tried following:

Select ID, Entry_date, sum(weight) as weight, sum(height) as height, ID1, start_date, end_date from table a 
where Entry_date >= start_date and Entry_date <= end_date group by ID, Entry_date;

But it is not giving me desired result. It is giving me following results:

  Table - a
          ID   Entry_date     weight  height   ID1      start_date  end_date
         111   2001-05-31      34      172     111      2001-04-30  2001-05-31 
         112   2001-07-31      26      188     112      2001-06-30  2001-07-31
         113   2001-05-31      34      172     113      2001-04-30  2001-05-31 
         114   2001-07-31      26      188     114      2001-06-30  2001-07-31

Can anyone please tell me how to proceed in this case?

This was a little complicated. Here's the query you could try:

select
  id, entry_date,

  (select sum(weight) from test 
   where entry_date between a.start_date and a.end_date
   and id = a.id) as weight,

  (select sum(height) from test
   where entry_date between a.start_date and a.end_date
   and id = a.id) as height,

  id1, start_date, end_date
from test a
where start_date is not null and end_date is not null

union all

select a.* 
from test a
left join test b 
  on a.id = b.id
where 
  (a.start_date is null and a.end_date is null)
  and (b.start_date is not null and b.end_date is not null)
  and not a.entry_date between b.start_date and b.end_date

order by id, entry_date

The query above the UNION ALL clause will pull records that does math on weight and height. The query below the UNION ALL clause only focuses on records that do not fall within the desired range and has null dates. You can tweak it to your comfort.

Example: http://sqlfiddle.com/#!9/f9b54a/6

Alternate method to query the same information

select e.id, 
    max(entry_date) as entry_date, sum(weight) as weight, sum(height) as height,
    em.start_date, em.end_date
from test e
inner join (
  select distinct id, start_date, end_date
  from test
  where start_date is not null and end_date is not null) em
  on em.id = e.id
  and e.entry_date between em.start_date and em.end_date
group by e.id, em.start_date, em.end_date

union all

select e.id, entry_date, weight, height, em.start_date, em.end_date
from test e
inner join (
  select distinct id, start_date, end_date
  from test
  where start_date is not null and end_date is not null) em
    on em.id = e.id
    and not e.entry_date between em.start_date and em.end_date

order by id, entry_date

Example: http://sqlfiddle.com/#!9/f9b54a/8

Better method to store data

create table entrymaster (
  id int,
  start_date date,
  end_date date
);

create table entries (
  id int,
  entry_date date,
  weight int,
  height int
);

select e.id, 
    max(entry_date) as entry_date, sum(weight) as weight, sum(height) as height,
    em.start_date, em.end_date
from entries e
inner join entrymaster em
  on em.id = e.id
  and e.entry_date between em.start_date and em.end_date
group by e.id, em.start_date, em.end_date

union all

select e.id, entry_date, weight, height, em.start_date, em.end_date
from entries e
inner join entrymaster em
    on em.id = e.id
    and not e.entry_date between em.start_date and em.end_date

order by id, entry_date

Example: http://sqlfiddle.com/#!9/7eaaa/3

Select ID, Entry_date, sum(weight) as weight, sum(height) as height, ID1, start_date, end_date from table a 
where Entry_date >= start_date and Entry_date <= end_date group by ID, Entry_date, ID1;

Added ID1 to the group by.

But this query may be not portable to some database engines, because you don't say to the server what value it should get from start_date and end_date if there is more than one line (first, min, max, etc).

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