mysql: Row count by date in between - mysql

From the screenshot shown, it is failed/missing to show the count of date
'2018-06-23' ,2018-06-25,2018-06-26,2018-06-27 , can you help me to write the correct query so that i get count of missing dates. I am trying to get count of total number of rows on particular date(created_date).
SELECT count(book_id) as count,created_date as cdate
FROM `bookdetails`
WHERE (created_date >= '2018-06-21' AND created_date <='2018-06-27')
GROUP by DATE(created_date)
ORDER BY MIN(created_date)
Expected output:
count | cdate
----------------------
98 2018-06-21
39 2018-06-22
0 2018-06-23 //because no data
39 2018-06-24
XX 2018-06-25
XX 2018-06-26
XX 2018-06-27
Table: bookdetails structure

Date generation and join need to show date that doest exist
select count(book_id) as count,date(C_date) as cdate from
(
select * from
(select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) C_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where C_date between '2018-01-01' and '2018-12-31'
) All_date
left join bookdetails
on date(created_date)=All_date.C_date
where ( date(All_date.C_date) >= '2018-06-21' AND date(All_date.C_date) <='2018-06-27')
group by date(C_date)
order by date(C_date) asc

Why not simply use BETWEEN instead of => and <=.
Usage:
SELECT * FROM bookdetails
WHERE created_date BETWEEN lowerdate AND upperdate
Show us your backend. We'll be able to assist you better.
And what is the expected result?

Related

MySQL get list of dates and join with another tab

I'm trying to generate seven rows for each date in the last seven days, and join with a query from transactions table. The aim is to have a table with each date, and the cumulative total of the quantity column in transactions from the first entry up to the date:
| date | stockOnDate |
|---------------|---------------|
| 2021-10-15 | 10 |
| 2021-10-16 | 3 |
| 2021-10-17 | 0 |
| 2021-10-18 | 9 |
| 2021-10-19 | 15 |
| 2021-10-20 | 15 |
| 2021-10-21 | 15 |
I can get the list of dates, and can join, but can't filter the nested queries:
SELECT v.*, t.*
FROM ( SELECT DATE(ADDDATE(DATE_SUB(NOW(),INTERVAL 7 DAY), t3*1000 + t2*100 + t1*10 + t0)) AS `date`
FROM (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3 ) AS v
LEFT JOIN (SELECT SUM(quantity) AS stockOnDate, DATE(timestamp) as tDate
FROM `transactions`
WHERE tDate <= v.`date`) AS t ON t.tDate = v.`date`
WHERE v.`date` >= DATE_SUB(NOW(),INTERVAL 7 DAY) AND v.`date` <= DATE(NOW())
But I'm receviing the following error:
#1054 - Unknown column 'tDate' in 'where clause'
If I replace WHERE tDate <= v.date with WHERE DATE(timestamp) <= v.date I get the same error for v.date - I can't seem to access the value of the parent tables.
I'm not great with MySQL but can't seem to find a solution, where am I going wrong?
Solution by ProGuru
Thanks to ProGuru's answer below, the below query works as expected (using <= instead of = in the JOIN was key)
SELECT b.date, SUM(a.quantity) AS stockOnDate
FROM (
SELECT DATE(ADDDATE(DATE_SUB(NOW(),INTERVAL 6 DAY), t3*1000 + t2*100 + t1*10 + t0)) AS `date`
FROM (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3
) b
LEFT JOIN transactions a ON DATE(a.timestamp) <= b.date
WHERE b.date BETWEEN DATE(NOW()) - INTERVAL 6 DAY AND DATE(NOW())
AND a.organisationId = 1
GROUP BY b.date
ORDER BY b.date ASC
I can also change the GROUP BY to GROUP BY a.itemID, b.date to get the stock level on the given date for each itemId.
To get the cumulative sum of quantity, the date join needs to use <=
Revised SQL
SELECT b.date, SUM(COALESCE(a.quantity, 0))
FROM (
SELECT DATE(ADDDATE(DATE_SUB(NOW(),INTERVAL 7 DAY), t3*1000 + t2*100 + t1*10 + t0)) AS `date`
FROM (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3
) b
LEFT JOIN transactions a ON DATE(a.timestamp) <= b.date
WHERE b.date BETWEEN DATE(NOW()) - INTERVAL 6 DAY AND DATE(NOW())
GROUP BY b.date
ORDER BY b.date ASC
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=34f78e3d7c9225727ac2e728588759e2
To use alias in where clause, you must encapsulate your query in another select.
Example :
SELECT * FROM
(SELECT SUM(quantity) AS stockOnDate, DATE(timestamp) as tDate FROM `transactions`) seb
WHERE seb.tDate <= v.`date`
Update try this:
SELECT v.*, t.*
FROM ( SELECT DATE(ADDDATE(DATE_SUB(NOW(),INTERVAL 7 DAY), t3*1000 + t2*100 + t1*10 + t0)) AS `date`
FROM (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3 ) AS v
LEFT JOIN (SELECT SUM(quantity) AS stockOnDate, DATE(timestamp) as tDate FROM transactions) AS t ON t.tDate = v.`date`
WHERE t.tDate <= v.`date` and v.`date` >= DATE_SUB(NOW(),INTERVAL 7 DAY) AND v.`date` <= DATE(NOW())
here tDate can be used
Firstly you need to understand that in this subquery
(SELECT SUM(quantity) AS stockOnDate, DATE(timestamp) as tDate
FROM `transactions`
WHERE tDate <= v.`date`) AS t
there is nothing defined as date or even the alias v. You're basically telling the query to look for v.date when it doesn't exists in the subquery.
I think this is what you're looking for:
SELECT dt, IFNULL(SUM(quantity),0) AS stockOnDate
FROM (SELECT STR_TO_DATE(CONCAT(LEFT(NOW(),7),LPAD(seq,2,0)), '%Y-%m%d') dt
FROM seq_1_to_31) v
LEFT JOIN `transactions` t ON dt=DATE(timestamp)
WHERE dt >= (SELECT MIN(DATE(timestamp)) FROM `transactions`)
AND dt <= (SELECT MAX(DATE(timestamp)) FROM `transactions`)
GROUP BY dt;
Here I'm using MariaDB's built-in sequence engine to generate days; concatenated with current year-month combination then uses STR_TO_DATE to make it recognizable as proper date format. The query generating those is in subquery v.
Second option is using a recursive common table expression to generate the date range based on existing date data in the table. Here is the query:
WITH RECURSIVE cte AS (
SELECT MIN(DATE(timestamp)) mndt, MAX(DATE(timestamp)) mxdt FROM `transactions`
UNION ALL
SELECT mndt+INTERVAL 1 DAY, mxdt FROM cte WHERE mndt+INTERVAL 1 DAY <= mxdt)
SELECT mndt, IFNULL(SUM(quantity),0) AS stockOnDate
FROM cte
LEFT JOIN `transactions` t ON mndt=DATE(timestamp)
GROUP BY mndt;
Both the query above eliminates the need to include a long subquery that generates the date range. This is the benefit of newer MySQL & MariaDB versions.
Demo fiddle

How to Get List of weeks between the given date range?

I want week list with week number, week start date and end date between two dates. Let me give you an example,
If I am passing start date as 2019-12-11 and end date as 2019-12-25, then expected output should look like below:
Week Number | Week start date | Week end date
W1 2019-12-11 2019-12-14
W2 2019-12-15 2019-12-21
W3 2019-12-22 2019-12-25
I have tried using below query but I got output like
Week start date | Week end date
2019-12-15 2019-12-21
2019-12-22 2019-12-28
select start_date, date_add(start_date, INTERVAL 6 DAY) as end_date
from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) start_date
from
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where start_date between '2019-12-11' and '2019-12-25'
AND date_format(start_date, '%w') = 0
You can use the following solution using WEEK function and ROW_NUMBER:
-- calendar table: https://stackoverflow.com/a/45992247/3840840
SELECT CONCAT('W', ROW_NUMBER() OVER (ORDER BY WEEK(start_date))) AS `Week Number`,
MIN(start_date) AS `Week start date`, MAX(start_date) AS `Week end date`
FROM (
SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS start_date
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) v
WHERE start_date BETWEEN '2019-12-11' AND '2019-12-25'
GROUP BY WEEK(start_date)
ORDER BY WEEK(start_date)
By using WEEK you don't have to calculate the weeks yourself. MySQL can detect the weeks. With WEEK you can get the week number of a date value. You can group by this week number to get the rows for every week. With MIN and MAX on the date value you get the first and last date of each week.
With ROW_NUMBER you can add a row number to your result. This function is available since MySQL 8.0. On earlier versions of MySQL you can use a solution like the following:
SELECT CONCAT('W', #row_number:=#row_number+1) AS `Week Number`,
MIN(start_date) AS `Week start date`, MAX(start_date) AS `Week end date`
FROM (
SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS start_date
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
ORDER BY start_date
) v, (SELECT #row_number:=0) rn
WHERE start_date BETWEEN '2019-12-11' AND '2019-12-25'
GROUP BY WEEK(start_date)
ORDER BY WEEK(start_date)
demo on dbfiddle.uk

Show all dates between, even if no result In group by

SELECT Count(Phq_2) as Phq_2, Date(created) as created
FROM `survey`
WHERE Phq_2 != ''
GROUP BY Date(created)
ORDER BY Date(created) ASC
Showing this
Expected Result
you can create a list of dates where you can use to list and join on your table. table c on the query below is the date table.
SELECT c.date,
COUNT(s.phq_2)
FROM (select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) date from
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4
) c
LEFT JOIN `survey` s
ON c.date = s.created
WHERE s.phq_2 != ''
AND c.date BETWEEN '2017-08-30' AND '2017-09-06'
GROUP BY c.date
ORDER BY c.date
Result
date COUNT(s.phq_2)
2017-08-30 1
2017-08-31 1
2017-09-01 0
2017-09-02 0
2017-09-03 0
2017-09-04 0
2017-09-05 1
2017-09-06 6
if you want the dates fixed for WHERE c.date BETWEEN '2017-08-30' AND '2017-09-06', you can use the resulting MIN() and MAX() of column created from your table in a sub-query

get Mondays between two dates mysql

I want to get the Mondays between two dates with a select statement, but I only have searched in sql server.
I have tried this, but it doesn´t work:
SELECT DATE_ADD('2017-01-01', INTERVAL ROW DAY) AS Date
FROM (
SELECT #row := #row + 1 AS row
FROM (
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t1,
(
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t2,
(
SELECT #row:=-1
) t3 LIMIT 31
) b
WHERE DATE_ADD('2017-01-01', INTERVAL ROW DAY) BETWEEN '2017-01-01' AND '2017-12-31'
AND DAYOFWEEK(DATE_ADD('2017-01-01', INTERVAL ROW DAY)) = 2
This query only gives me the Monday´s date for one month.
I hope that you can help me
Regards!
If you really want to solve this SQL only, you have to delve a bit deeper and generate a sequence of days, this is by far the most difficult side task to solve this. Besides this, as you have already guessed, you can use DAYOFWEEK or WEEKDAY to get your desired days.
SELECT *
FROM (
SELECT DATE_ADD('2013-01-01',
INTERVAL n4.num*1000+n3.num*100+n2.num*10+n1.num DAY ) AS DATE
FROM (
SELECT 0 AS num
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 n1,
(
SELECT 0 AS num
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 n2,
(
SELECT 0 AS num
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 n3,
(
SELECT 0 AS num
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 n4
) AS a
WHERE DATE >= '2017-01-01' AND DATE < NOW()
AND WEEKDAY(DATE) = 0
ORDER BY DATE
Some other RDBMS have inbuild functions for that.
If would be way easier if you have a calendar table where all dates are already present.
I think that this solution will work with better performance than previous
SET #date_start = date('2019-07-06');
SET #date_end = date('2019-09-18');
SELECT CASE WHEN MOD(DAYOFWEEK(#date_start), 7) <= 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 2 OR
MOD(DAYOFWEEK(#date_start), 7) > 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 9 THEN 1 ELSE 0 END
+ FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) num_of_mo
, #date_start start_date,v.selected_date end_date
FROM (select adddate(#date_start,t4*10000 + t3*1000 + t2*100 + t1*10 + t0) selected_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
WHERE v.selected_date <= #date_end;

How to display all date values as null in a date range of mysql?

I have a table of booking and need to find the count of booking in a specific date range in MYSQL. But it is giving me only non empty values. I need to show the non existence date within range as NULL in my select query. Here is my query:
SELECT DATE_FORMAT(booking_created_on, '%b %e') AS dateValue , COUNT(booking_id) AS cnt FROM booking WHERE booking_created_on BETWEEN '2016/02/01' AND '2016/02/08' GROUP BY booking_created_on
My result from this query is :
And my expected result is:
Please help me in mysql query for getting the desired result.
Try This
SELECT DATE_FORMAT(selected_date, '%b %e'), cnt
FROM(
SELECT
str_to_date(booking_created_on, '%Y/%m/%d') AS selected_date ,
COUNT(booking_id) AS cnt
FROM booking
WHERE booking_created_on BETWEEN '2016/02/01' AND '2016/02/08'
GROUP BY booking_created_on
UNION
SELECT selected_date,0 AS cnt FROM
(SELECT adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date FROM
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) v
where selected_date BETWEEN '2016-02-01' and '2016-02-08' AND selected_date NOT IN (
SELECT
DISTINCT(str_to_date(booking_created_on, '%Y/%m/%d')) FROM booking
WHERE booking_created_on BETWEEN '2016/02/01' AND '2016/02/08'
)
) AS T1
ORDER BY selected_date ;
In my query, first i get all date and count in your table and in second subquery i get all missing date which is not in your table between two dates. show result order by date. this is lengthy query so may be it will be some error so if any error, comment