Return 0 for hours with no sales

I've got the following query:


SELECT DATEPART(hour, TimeStamp) AS Hour
, SUM(cast(Amount as money)) AS Sales
FROM billingTransactions
WHERE DATEADD(day, 0, DATEDIFF(day, 0, TimeStamp)) = '07/06/2009'
GROUP BY DATEPART(hour, TimeStamp)
ORDER BY hour

I want it to return a 0 for hours where there are no sales.....  This works well, but only returns those hours with actual sales.
pazzaTimAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Aneesh RetnakaranDatabase AdministratorCommented:
;with cte (i) as (
Select 1 as i
union all
select i+1 as i
from cte )

SELECT i AS Hour
, ISNULL( SUM(cast(Amount as money)),0) AS Sales
FROM billingTransactions
LEFT Join CTE c ON c.i = DATEPART(hour, TimeStamp)
WHERE DATEADD(day, 0, DATEDIFF(day, 0, TimeStamp)) = '07/06/2009'
GROUP BY DATEPART(hour, TimeStamp)
order by hour
OPTION (MAXRECURSION 24)
0
pazzaTimAuthor Commented:
Not working... First it said that cte.i not in group by, when I added it, we got max recursions...
0
pazzaTimAuthor Commented:
The statement terminated. The maximum recursion 24 has been exhausted before statement completion.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Aneesh RetnakaranDatabase AdministratorCommented:
instead of cte you can populate a temptable with 24 hours and you juts need to join that table

SELECT i AS Hour
, ISNULL( SUM(cast(Amount as money)),0) AS Sales
FROM billingTransactions
LEFT Join @tempTable  c ON c.i = DATEPART(hour, TimeStamp)
WHERE DATEADD(day, 0, DATEDIFF(day, 0, TimeStamp)) = '07/06/2009'
GROUP BY DATEPART(hour, TimeStamp)
order by hour
OPTION (MAXRECURSION 24)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
pazzaTimAuthor Commented:
SELECT CTE.HR, ISNULL(SS.TOTAL,0) AS TOTAL
FROM (
SELECT DISTINCT DATEPART(hour, TimeStamp) AS HR
FROM billingTransactions
) CTE
LEFT OUTER JOIN (
SELECT DATEPART(hour, TimeStamp) AS HR, SUM(CAST(Amount AS money)) AS TOTAL
FROM billingTransactions
WHERE DATEADD(day, 0, DATEDIFF(day, 0, TimeStamp)) = '07/06/2009'
GROUP BY DATEPART(hour, TimeStamp)
) SS
ON CTE.HR = SS.HR
order by hr
0
rob_farleyCommented:
If you were to archive off most of your records in billingTransactions, you'll find this no longer produces all your hours.

So why not go with:

WITH AllHours AS (
SELECT 0 AS Hour
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 UNION ALL SELECT 10
UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15
UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20
UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23)
SELECT H.Hour, SS.Total
FROM AllHours H
  LEFT OUTER JOIN (
SELECT DATEPART(hour, TimeStamp) AS HR, SUM(Amount) AS Total
FROM billingTransactions
WHERE TimeStamp >= '20090706' AND TimeStamp < '20090707'
GROUP BY DATEPART(hour, TimeStamp)
) SS
ON H.Hour = SS.HR
ORDER BY H.Hour;

You'll also notice that I have changed the WHERE clause, so that I'm not fiddling with the TimeStamp column. This means that a non-clustered index like:

create index ixTimeStampAmont on billingTransactions(TimeStamp) include (Amount);

...will make this query much faster.

Also, the ORDER BY is now specifying a table alias, to make sure there's no ambiguity.

Hope this helps complete the picture...

Rob
0
rob_farleyCommented:
pazzaTim should assign some points here...
0
rob_farleyCommented:
I think if pazzaTim found that the answer he wrote was the best, then it's fine to Accept that one as the answer, but as the Asker, he should've given the points to those that helped.

So... Accept with 50, and give 450 away to the other experts who contributed.

Rob
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft SQL Server 2008

From novice to tech pro — start learning today.