Reputation: 8790
vwSalesByHour works as expected showing only records for hours in which there were sales. Naturally, vwCumulativeDaySalesByHour also shows only records for hours in which there were sales but I need it to show a record for every hour of the day. I know there has to be a simple way to do this easier than what I've thought of so far... if someone would just be so kind as to point it out to me :)
--This works great
CREATE VIEW vwSalesByHour AS
select SUM(t.TranAmount - t.DeliveryFee - t.TaxAmount) Sales,
BusinessDate,
DATEPART(HH, OrderTime) Hour
from transactions t
where TranState <> 11 and TicketNumber > 0
group by BusinessDate, DATEPART(HH, OrderTime)
--But I would like this to return records for all 24 hours
CREATE VIEW vwCumulativeDaySalesByHour
AS
select min(s1.Sales) Sales,
sum(s2.Sales) CumulativeSales,
s1.BusinessDate, s1.Hour
from SalesByHour s1 join
SalesByHour s2 on s1.BusinessDate = s2.BusinessDate and
s1.Hour >= s2.Hour
group by s1.BusinessDate, s1.Hour
Upvotes: 1
Views: 528
Reputation: 86765
Generally, I recommend changing your design to not require this. But, if you do really need it; Create templates to join on, these ensure that you have every record that you need.
You might have a calendar table with every day pre-populated. And maybe an hourly table with 24 hours populated. Or one table composing everything you could need (year, month, week, day, hour, interval, etc, as different columns, and then with multiple covering indexes).
Even at the extreme, this normally doesn't take much space, and does drastically simplify queries and (normally) saves significant processing time.
You then get something like this...
SELECT
calendar.date,
hours.hour,
SUM(SalesByHour.Sales) AS CumulativeSales,
MAX(CASE WHEN SalesByHour.Hour = hours.hour THEN Sales.Sales ELSE NULL END) AS Sales
FROM
calendar
CROSS JOIN
hours
LEFT JOIN
SalesByHour
ON SalesByHour.BusinessDate = calendar.date
AND SalesByHour.Hour <= hours.hour
GROUP BY
calendar.date,
hours.hour
The alternative is just to populate the gaps in your client. But this my distribute certain logic across client and SQL. The exact best way to avoid this need is situation dependent. But I do recommend finding a way of not needing this if it is t all possible.
The same goes for the cumulative values. SQL is notoriously poor at running totals like this. If the client can process the running total instead of the SQL, you probably get decent overall performance saving.
Upvotes: 1