0

I'm trying to select data between two date range. However not all data are being inserted daily. Below is sample of the table:

mysql> SELECT * FROM attendance;
+------------+-------+
| date       | total |
+------------+-------+
| 2012-07-02 |   100 |
| 2012-07-04 |    70 |
| 2012-07-05 |    78 |
+------------+-------+
3 rows in set (0.00 sec)

The scenario is I want to get total of attendance from 2012-07-02 till 2012-07-04. Based on the data above I will get

mysql> SELECT * FROM attendance WHERE date BETWEEN '2012-07-02' AND '2012-07-04';
+------------+-------+
| date       | total |
+------------+-------+
| 2012-07-02 |   100 |
| 2012-07-04 |    70 |
+------------+-------+
2 rows in set (0.00 sec)

However my objective is to have 2012-07-03 included in the result.

+------------+-------+
| date       | total |
+------------+-------+
| 2012-07-02 |   100 |
| 2012-07-03 |     0 |
| 2012-07-04 |    70 |
+------------+-------+

Is this possible to be done through MySQL? I did look into temporary table. But still unable to achieve the objective.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Rashidi Zin
  • 266
  • 2
  • 4
  • 18

3 Answers3

1

You can enumerate dates as derived pseudo-table (with UNION) and then join it with your data

SELECT dates.date, COALESCE(attendance.total,0) AS total FROM (
SELECT '2012-07-02' AS date
UNION ALL SELECT '2012-07-03'
UNION ALL SELECT '2012-07-04'
) AS dates
LEFT JOIN attendance USING(date)

Edit: added COALESCE to return 0 instead of NULL on missing records.

vearutop
  • 3,924
  • 24
  • 41
0

MySQL cannot generate data that isn't there. If you want non-existent dates, you'll need to have a temporary table that contains the full date range you join against. Another alternative is to maintain a server-side variable and do some date math for each row, which is ugly

select @dateval := '2012-07-02';
SELECT @dateval := @dateval + INTERVAL 1 DAY from ...
Marc B
  • 356,200
  • 43
  • 426
  • 500
0

This is a common problem with a simple solution.

Create a regular table, say REF_DATE, and store in it all dates for like 3 years or whatever time span you would need.

Then use this table on the left of a LEFT OUTER JOIN

SELECT REF.date,IFNULL(A.total,0) as total FROM REF_DATE REF 
LEFT OUTER JOIN attendance 
ON REF.date=A.date
A WHERE REF.date BETWEEN '2012-07-02' AND '2012-07-04';

DATE is a keyword in MySQL, I have used it here for readability. Use a different column name.

Dojo
  • 5,374
  • 4
  • 49
  • 79
  • Thanks. The provided SQL didn't actually work. A minor fix got the job done. `SELECT REF.date, IFNULL(A.total, 0) as total FROM REF_DATE REF LEFT OUTER JOIN attendance A ON REF.date = A.date WHERE REF.date BETWEEN '20-07-02' AND '2012-07-04';` – Rashidi Zin Jul 05 '12 at 07:33
  • 1
    To whoever has downvoted this - Have the decency to comment why you downvoted it. – Dojo Oct 27 '15 at 11:54