I have these two tables:
Operators:
Id Nome
--+----
1 JDOE
2 RROE
3 MMOE
Calls:
Id CallDate OpId
--+--------+----
1 20161228 2
2 20161228 3
3 20161228 2
4 20161228 3
5 20170104 1
6 20170104 2
7 20170104 1
And this query:
SELECT Operators.id, Operators.Nome, Count(Calls.OpId) AS CountCalls
FROM Operators LEFT JOIN Calls ON Operators.id = Calls.OpId
GROUP BY Calls.CallDate, Operators.id, Operators.Nome
HAVING Calls.CallDate=20170104;
Which returns:
Id Nome CountCalls
--+----+----------
1 JDOE 2
2 RROE 1
How can I make it return this, instead?
Id Nome CountCalls
--+----+----------
1 JDOE 2
2 RROE 1
3 MMOE 0
That is, how to include in any query also the zero results from main table which has no occurrence in left joined table, at least in the data slice defined by the query filtering criteria?
This is Access 2013.
I've read this answer but couldn't see how it is different from what I'm doing.
Because you have a reference to Calls.CallDate
in your HAVING
clause, you are removing operators where there are no calls. If there were no calls, then CallDate
would be NULL
, and NULL=20170104
is not true, so these rows are excluded. You need to move this predicate to your join clause:
SELECT Operators.id, Operators.Nome, Count(Calls.OpId) AS CountCalls
FROM Operators LEFT JOIN Calls ON (Operators.id = Calls.OpId AND Calls.CallDate=20170104)
GROUP BY Calls.CallDate, Operators.id, Operators.Nome;
You also don't need to group by Calls.CallDate
, since you only have one anyway, so you can just use:
SELECT Operators.id, Operators.Nome, Count(Calls.OpId) AS CountCalls
FROM Operators LEFT JOIN Calls ON (Operators.id = Calls.OpId AND Calls.CallDate=20170104)
GROUP BY Operators.id, Operators.Nome;
As an aside HAVING
is the wrong operator. HAVING
is for filtering aggregates, since you are not filtering an aggregate, you should simply use WHERE
SELECT Operators.id, Operators.Nome, Count(Calls.OpId) AS CountCalls
FROM Operators LEFT JOIN Calls ON Operators.id = Calls.OpId
WHERE Calls.CallDate=20170104
GROUP BY Calls.CallDate, Operators.id, Operators.Nome;
You would use HAVING
if you wanted to fliter on CountCalls
, e.g if you only wanted operators that had made more than 1 call you might use:
SELECT Operators.id, Operators.Nome, Count(Calls.OpId) AS CountCalls
FROM Operators LEFT JOIN Calls ON Operators.id = Calls.OpId
WHERE Calls.CallDate=20170104
GROUP BY Calls.CallDate, Operators.id, Operators.Nome
HAVING Count(Calls.OpId) > 1;
This would only return
Id Nome CountCalls
--+----+----------
1 JDOE 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With