3

I have searched similar problems here on stackoverflow but I could not understand how to make this work, what I'm trying to do...

So, I want to get last 7 days transactions from database and get total sales amount and also include empty rows if there is no data for some day.

What I have so far: http://sqlfiddle.com/#!2/f4eda/6

This outputs:

| PURCHASE_DATE | AMOUNT |
|---------------|--------|
|    2014-04-25 |     19 |
|    2014-04-24 |     38 |
|    2014-04-22 |     19 |
|    2014-04-19 |     19 |

What I want:

| PURCHASE_DATE | AMOUNT |
|---------------|--------|
|    2014-04-25 |     19 |
|    2014-04-24 |     38 |
|    2014-04-23 |      0 |
|    2014-04-22 |     19 |
|    2014-04-21 |      0 |
|    2014-04-20 |      0 |
|    2014-04-19 |     19 |

Any help appreciated :)

plexcell
  • 1,647
  • 2
  • 15
  • 29
  • possible duplicate of [Mysql: Select all data between two dates](http://stackoverflow.com/questions/1080207/mysql-select-all-data-between-two-dates) – Marcus Adams Apr 25 '14 at 18:44

4 Answers4

16

This is not easy. I took help from this thread generate days from date range and combined it with your query.

So the idea was to get the list of dates from last 7 days then left join these dates with a static amount 0 to the query you have and then finally sum them. This could be used for any date range, just need to change them in both the queries

select 
t1.purchase_date,
coalesce(SUM(t1.amount+t2.amount), 0) AS amount
from
(
  select DATE_FORMAT(a.Date,'%Y-%m-%d') as purchase_date,
  '0' as  amount
  from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
  ) a
  where a.Date BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
)t1
left join
(
  SELECT DATE_FORMAT(purchase_date, '%Y-%m-%d') as purchase_date,
  coalesce(SUM(amount), 0) AS amount
  FROM transactions
  WHERE purchase_date BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
  AND vendor_id = 0
  GROUP BY purchase_date
)t2
on t2.purchase_date = t1.purchase_date
group by t1.purchase_date
order by t1.purchase_date desc

DEMO

Community
  • 1
  • 1
Abhik Chakraborty
  • 44,654
  • 6
  • 52
  • 63
4

Simply put together a subquery with the dates you want and use left outer join:

select d.thedate, coalesce(SUM(amount), 0) AS amount
from (select date('2014-04-25') as thedate union all
      select date('2014-04-24') union all
      select date('2014-04-23') union all
      select date('2014-04-22') union all
      select date('2014-04-21') union all
      select date('2014-04-20') union all
      select date('2014-04-19')
     ) d left outer join
     transactions t
     on t.purchase_date = d.thedate and vendor_id = 0
GROUP BY d.thedate
ORDER BY d.thedate DESC;
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • Thanks, but its giving some error http://sqlfiddle.com/#!2/f4eda/41 Exception -> string(282) "SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union all select date('2014-04-23' union all select date' at line 3" – plexcell Apr 25 '14 at 19:00
0

This is for last 7 days;

select d.thedate, coalesce(SUM(amount), 0) AS amount
from (select DATE(NOW()) as thedate union all
      select DATE(DATE_SUB( NOW(), INTERVAL 1 DAY)) union all
      select DATE(DATE_SUB( NOW(), INTERVAL 2 DAY)) union all
      select DATE(DATE_SUB( NOW(), INTERVAL 3 DAY)) union all
      select DATE(DATE_SUB( NOW(), INTERVAL 4 DAY)) union all
      select DATE(DATE_SUB( NOW(), INTERVAL 5 DAY)) union all
      select DATE(DATE_SUB( NOW(), INTERVAL 6 DAY))) d left outer join
     transactions t
     on t.purchase_date = d.thedate and vendor_id = 0
GROUP BY d.thedate
ORDER BY d.thedate DESC;
0
with recursive all_dates(dt) as (
    select '2014-04-19' as dt
    union all 
    select dt + interval 1 day
    from all_dates
    where dt + interval 1 day <= '2014-04-25'
)
select d.dt as purchase_date, coalesce(m.amount, 0) as purchased
from all_dates as d
left join mytable m
on d.dt = m.purchase_date
order by purchase_date desc;
Ebo
  • 1
  • 1
  • 1
    While this might answer the question, you should [edit] your answer to include a short explanation of *how* this script answers the question. This helps to give context and makes the answer much more useful to those who might come across the same issue later on. – Hoppeduppeanut Jul 19 '20 at 23:00