Get zero for a count at dates without records
Create a table that contains all dates. Then do a left join with the Activity table. Group on the date, and do a COUNT
on Activity.id. The left join ensures that all dates from the date table are included in the result set, even if they are not matched in the join clause.
MySQL show count of 0 for dates with no records
Ok from my previous answer from the thread MySql Single Table, Select last 7 days and include empty rows
Here what you can do for making the date selection dynamic
select
t1.attempt_date,
coalesce(SUM(t1.attempt_count+t2.attempt_count), 0) AS attempt_count
from
(
select DATE_FORMAT(a.Date,'%Y/%m/%d') as attempt_date,
'0' as attempt_count
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(attempt_date,'%Y/%m/%d') AS attempt_date,
COUNT(*) AS attempt_count
FROM users_attempts
WHERE DATE_SUB(attempt_date, INTERVAL 1 DAY) > DATE_SUB(DATE(NOW()), INTERVAL 1 WEEK)
GROUP BY DAY(attempt_date) DESC
)t2
on t2.attempt_date = t1.attempt_date
group by DAY(t1.attempt_date)
order by t1.attempt_date desc;
DEMO
How to deal: my 'count' query does not get zero, when records not exist
Use Join
with Group By
SELECT cu.id,cu.name,COUNT(cu.id) AS [COUNT],cu.ipn,cu.address,cu.number,cu.email
FROM Customer cu
JOIN Car ca ON cu.id = ca.customer_id
GROUP BY cu.id,cu.name,cu.ipn,cu.address,cu.number,cu.email
MYSQL return zero in date not present, and COUNT how many rows are present with a specific date
Consider:
select c.mydate, count(d.id) number_of_orders
from calendar c
left join delivery d on d.giorno = c.mydate
group by c.mydate
This works by left-joining the calendar table with the orders table, then aggregating by date, and finally counting the number of matching rows in the order table.
This is quite close to your original query (although this uses left join
instead of right join
), however this uses an aggregate function to count the orders.
mysql show count as 0 for non-existing records
You need to generate the dates dynamically for this and then use left join. Also note that since you are displaying the user_id
it might be needed a cross join of distinct user_id
with the dynamically generated dates.
From my previous answers related to showing missing dates MySql Single Table, Select last 7 days and include empty rows
Here is one for your case
select
t1.user_id,
coalesce(t2.cnt,0) as cnt,
t1.view_date
from
(
select DATE_FORMAT(a.Date,'%Y-%m-%d') as view_date,
x.user_id
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,(select distinct user_id from user_views)x
where a.Date between DATE_SUB(DATE(NOW()), INTERVAL 90 DAY) AND now()
)t1
left join
(
select user_id, count(user_id) as cnt, Date(view_time) as view_time from user_views
where DATE(view_time) between DATE_SUB(DATE(NOW()), INTERVAL 90 DAY) AND now()
group by user_id, date(view_time)
)t2
on t2.view_time = t1.view_date
and t1.user_id = t2.user_id
order by t1.view_date,t1.user_id
http://sqlfiddle.com/#!2/4136e/5
How to include zero / 0 results in COUNT aggregate?
You want an outer join for this (and you need to use person as the "driving" table)
SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person
LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;
The reason why this is working, is that the outer (left) join will return NULL
for those persons that do not have an appointment. The aggregate function count()
will not count NULL
values and thus you'll not get a zero.
If you want to learn more about outer joins, here is a nice tutorial: http://sqlzoo.net/wiki/Using_Null
Count registers by day including zero
You can use a Calendar or dates table for this sort of thing.
For only 152kb in memory, you can have 30 years of dates in a table with this:
/* dates table */
declare @fromdate date = '20000101';
declare @years int = 30;
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate)))
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
into dbo.Dates
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date];
create unique clustered index ix_dbo_Dates_date
on dbo.Dates([Date]);
Without taking the actual step of creating a table, you can use it inside a common table expression with just this:
declare @fromdate date = dateadd(day , datediff(day , 0, getdate() )-30 , 0);
declare @thrudate date = dateadd(day , datediff(day , 0, getdate() ), 0);
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (datediff(day, @fromdate, @thrudate)+1)
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date]
)
select [Date]
from dates;
Use either like so:
select
d.Date
, count(t.DownloadDate) as DownloadCount
from dates d
left join TBL_Downloads t
on d.date = convert(date,t.DownloadDate)
and t.userid = 292
where d.date >= dateadd(day , datediff(day , 0, getdate() )-30 , 0)
and d.date <= dateadd(day , datediff(day , 0, getdate() ), 0)
group by d.date
rextester demo: http://rextester.com/ISK37732 (dates changed to be within last 30 days)
returns:
+------------+---------------+
| Date | DownloadCount |
+------------+---------------+
| 2017-02-27 | 0 |
| 2017-02-28 | 0 |
| 2017-03-01 | 2 |
| 2017-03-02 | 1 |
| 2017-03-03 | 0 |
| 2017-03-04 | 1 |
| 2017-03-05 | 1 |
| 2017-03-06 | 1 |
| 2017-03-07 | 0 |
| 2017-03-08 | 0 |
| 2017-03-09 | 0 |
| 2017-03-10 | 0 |
| 2017-03-11 | 0 |
| 2017-03-12 | 0 |
| 2017-03-13 | 0 |
| 2017-03-14 | 0 |
| 2017-03-15 | 0 |
| 2017-03-16 | 0 |
| 2017-03-17 | 0 |
| 2017-03-18 | 0 |
| 2017-03-19 | 0 |
| 2017-03-20 | 0 |
| 2017-03-21 | 0 |
| 2017-03-22 | 0 |
| 2017-03-23 | 0 |
| 2017-03-24 | 0 |
| 2017-03-25 | 0 |
| 2017-03-26 | 0 |
| 2017-03-27 | 0 |
| 2017-03-28 | 0 |
| 2017-03-29 | 0 |
+------------+---------------+
Number and Calendar table reference:
- Generate a set or sequence without loops - 1 - Aaron Bertrand
- Generate a set or sequence without loops - 2 - Aaron Bertrand
- Generate a set or sequence without loops - 3 - Aaron Bertrand
- The "Numbers" or "Tally" Table: What it is and how it replaces a loop - Jeff Moden
- Creating a Date Table/Dimension in sql Server 2008 - David Stein
- Calendar Tables - Why You Need One - David Stein
- Creating a date dimension or calendar table in sql Server - Aaron Bertrand
- tsql Function to Determine Holidays in sql Server - Aaron Bertrand
- F_table_date - Michael Valentine Jones
Related Topics
Comma Delimited SQL String Need to Separated
How to Return a JSONb Array and Array of Objects from My Data
Foreign Key for Either-Or Column
How to Better Duplicate a Set of Data in SQL Server
Syntax Error (Missing Operator) in Query Expression in Ms Access
Calling a Stored Proc Over a Dblink
Ms Access Query with Case Statement
Generally, Are String (Or Varchar) Fields Used as Join Fields
How to Retrieve Rows Multiple Times in SQL Server
As400 SQL Query with Parameter
How to Display Column Headers Returned by Postgresql Function
Oracle Equivalent of Rowlock, Updlock, Readpast Query Hints
Join/Pivot Items with Eav Table
Why Isn't Postgres Using the Index
Mysql, Delete Query with a Join
Escaping Command Parameters Passed to Xp_Cmdshell to Dtexec
Transpose a Row into Columns with MySQL Without Using Unions