Reputation: 41
I have a customer table and an orders table In this case I would like to have a monthly report about how many customer didn't place any order Like this Month Number of inactive customer
I have written a query like this:
SELECT Count (distinct Persons.id), Month (Orders.OrderDate) FROM Persons LEFT JOIN Orders ON Persons.id = Orders.Person_id WHERE Orders.Person_id IS NULL; Group By Month (Orders.OrderDate)
Due to the condition IS NULL, then the result of Month (OrderDate) is also NULL How should I let the month also be displayed? I am using tsql
Upvotes: 0
Views: 1055
Reputation: 1270643
Generate a list of dates. One method is a recursive CTE to generate the list. Then count the total number of people and subtract the ones who have not made an order:
with dates as (
select convert(date, '2019-01-01') as dte
union all
select dateadd(month, 1, dte)
from dates
where dte < getdate()
)
select d.dte, p.total - count(distinct o.personid)
from dates d left join
orders o
on o.orderdate >= d.dte and
o.orderdate < dateadd(month, 1, d.dte) cross join
(select count(*) as total from person) p
group by d.dte
order by d.dte;
Actually, if someone places an order very month, then there is no need for the CTE:
select datefromparts(year(o.orderdate), month(o.orderdate), 1) as yyyymm,
p.total - count(distinct o.person_id)
from orders o cross join
(select count(*) as total from person) p
group by datefromparts(year(o.orderdate), month(o.orderdate), 1), p.total
order by min(orderdate);
Upvotes: 1
Reputation: 222612
If you have at least one order per months in table orders
, then you can cross join
the persons with the distinct months, and filter on inactive clients with a not exists
condition:
select d.ordermonth, count(*) no_inactive_clients
from persons p
cross join (select distinct datefromparts(year(orderdate), month(orderdate), 1) ordermonth from orders) d
where not exists (
select 1
from orders o
where
o.orderdate >= d.ordermonth
and o.orderdate < dateadd(month, 1 d.ordermonth)
and o.person_id = p.id
)
group by d.ordermonth
If there are months without any order, they will not show in the resultset though. In that case, you need a calendar table instead; you can store it permanently, or generate it with a recursice CTE or a tally.
Upvotes: 2