Question : How can I include months with zero rows in a Sales By Month report

Hi Guys,

I have TSQL to get me the data for a report / graph showing sales by month.  However, whilst it returns the correct values if there are no rows for a particular month nothing is returned.  In such a situation I need to return an additional row with a zero value for each missing month.

How can I best achieve this please?  

Chris Bray
1:
2:
3:
4:
5:
6:
7:
8:
9:
SELECT YEAR(TransactionDate) AS TransactionYear,
MONTH(TransactionDate) AS TransactionMonth,
SUM(Coalesce(BaseDebitAmount, 0)-Coalesce(BaseCreditAmount, 0)) AS GrossMonthlySales
FROM GeneralJournal
WHERE MasterRecord 
AND (TransactionTypeId = 12 OR TransactionTypeId = 13 OR TransactionTypeId = 14) 
AND TransactionDate BETWEEN '01/11/2009 00:00:00' AND '31/10/2010 23:59:59'
GROUP BY YEAR(TransactionDate), MONTH(TransactionDate)
ORDER BY TransactionYear, TransactionMonth;

Answer : How can I include months with zero rows in a Sales By Month report

>> Again, not entirely practical.  We would end up with a huge table with every day from MinDate to MaxDate included.  There has to be a better way? <<

I agree.

Instead, create a table of sequential numbers -- a "tally" table, if you don't already have one.
Then you can do something like below.

RE: mechanics of the tally table::
Just sequential numbers from 0 to whatever, say 100,000.  Specify a unique, clustered index on the number, with a fillfactor of 100 (this table will never be UPDATEd or INSERTed between existing rows, so there is no need for freespace in the table).  For max performance, set it to readonly (if/when you need to add rows, naturally you would temporarily set it to updateable again).
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
DECLARE @startDate datetime
DECLARE @endDate datetime

SELECT YEAR(DATEADD(MONTH, sn.num, TransactionDate)) AS TransactionYear,
MONTH(DATEADD(MONTH, sn.num, TransactionDate)) AS TransactionMonth,
SUM(Coalesce(BaseDebitAmount, 0)-Coalesce(BaseCreditAmount, 0)) AS GrossMonthlySales

FROM sequentialNumbersTable sn 
LEFT OUTER JOIN GeneralJournal ON TransactionDate BETWEEN DATEADD(MONTH, sn.num, @startDate) AND DATEADD(MS, -3, DATEADD(MONTH, sn.num + 1, @startDate))

WHERE sn.tally BETWEEN 0 AND DATEDIFF(MONTH, @startDate, @endDate)
AND ...other conditions as before...
Random Solutions  
 
programming4us programming4us