英文:
SQL Fill in 0 for the rows with no data
问题
I can provide a translation of the code portion for you. Here it is:
with mycte as
(
SELECT 0 AS MyHour
UNION ALL
SELECT MyHour + 1
FROM mycte
WHERE MyHour + 1 < 24
)
SELECT h.SalesDay, FORMAT(DATEADD(hour, mycte.MyHour, '00:00'), 'HH:mm') AS SalesByHour, COALESCE(ReceiptCount, 0) AS HourlySales FROM mycte
LEFT JOIN
(
SELECT
DATENAME(WEEKDAY, TRANDATETIME) AS SalesDay,
DATEPART(hour, TRANDATETIME) AS SalesByHour,
COUNT(REF) as ReceiptCount
FROM [RC_BACK].[dbo].[TRAN]
WHERE TRANCODE = 'SA'
GROUP BY DATENAME(WEEKDAY, TRANDATETIME), DATEPART(hour, TRANDATETIME)
) h
ON h.SalesByHour = mycte.MyHour
ORDER BY h.SalesDay, SalesByHour ASC
Please let me know if you need any further assistance.
英文:
I am trying to generate a table that have receipt count group by days of the week and every hour of a day. I want the table include the day and hour that have no record and will fill it in with 0 for the receipt count. For example, I want the query to return a table with something like this:
SalesDay | SalesByHour | ReceiptCount |
---|---|---|
Monday | 00:00 | 0 |
Monday | 01:00 | 0 |
Monday | 02:00 | 0 |
Monday | 03:00 | 0 |
Monday | 04:00 | 0 |
Monday | 05:00 | 200 |
Monday | 06:00 | 200 |
Monday | 07:00 | 200 |
Monday | 08:00 | 200 |
Monday | 09:00 | 0 |
Monday | 10:00 | 200 |
Monday | 11:00 | 200 |
Monday | 12:00 | 0 |
Monday | 13:00 | 200 |
Monday | 14:00 | 200 |
Monday | 15:00 | 200 |
Monday | 16:00 | 0 |
Monday | 17:00 | 200 |
Monday | 18:00 | 200 |
Monday | 19:00 | 200 |
Monday | 20:00 | 200 |
Monday | 21:00 | 200 |
Monday | 22:00 | 200 |
Monday | 23:00 | 0 |
And the rest of the table will resume with Tuesday, Wednesday and so on until Sunday with every hour of a day in the table as above. The day of the week is generated with DATENAME() function and the hours of the day is generated with CTE as I don't have a table for the weekdays and hours. My query as of now will only return results with days and hours that have records in the database. My query is as below:
with mycte as
(
SELECT 0 AS MyHour
UNION ALL
SELECT MyHour + 1
FROM mycte
WHERE MyHour + 1 < 24
)
SELECT h.SalesDay, FORMAT(DATEADD(hour,mycte.MyHour,'00:00'),'HH:mm') AS SalesByHour, COALESCE(ReceiptCount,0) AS HourlySales FROM mycte
LEFT JOIN
(
SELECT
DATENAME(WEEKDAY, TRANDATETIME) AS SalesDay,
DATEPART(hour, TRANDATETIME) AS SalesByHour,
COUNT(REF) as ReceiptCount
FROM [RC_BACK].[dbo].[TRAN]
WHERE TRANCODE = 'SA'
GROUP BY DATENAME(WEEKDAY, TRANDATETIME), DATEPART(hour, TRANDATETIME)
) h
ON h.SalesByHour = mycte.MyHour
ORDER BY h.SalesDay, SalesByHour ASC
and results are as below:
What do I need to add for my query so that it will have the results that I want?
答案1
得分: 1
以下是代码的翻译部分:
正如 @DaleK 所指出的,理想的解决方案是使用一种包含日期和小时的日历表,并在代码中使用它。以下是使用您已经使用的 CTE 方法的解决方案:
WITH cte_hours
AS (
SELECT 0 AS [hour]
UNION ALL
SELECT [hour] + 1
FROM cte_hours
WHERE [hour] + 1 < 24
)
, cte_days
AS (
SELECT daynm, [dayname]
FROM (
VALUES
(0,'星期一') ,(1,'星期二') ,(2,'星期三') ,(3,'星期四') ,(4,'星期五') ,(5,'星期六') ,(6,'星期日')
) a(daynm, [dayname])
)
/*示例销售数据集*/
, cte_sales
AS (
SELECT [hour], [dayname], [hourlysales]
FROM (
VALUES
(4,'星期一', 100), (14,'星期一', 110), (5,'星期一', 20), (6,'星期一', 10), (21,'星期一', 3),(3,'星期一', 50)
,(11,'星期二', 3), (12,'星期二', 15), (9,'星期二', 155), (2,'星期二', 25)
,(12,'星期三', 125) ,(14,'星期三', 9) ,(11,'星期三', 95)
,(13,'星期四', 42), (23,'星期四', 342), (6,'星期四', 123)
,(20,'星期五', 9),(4,'星期五', 93)
,(15,'星期六', 32),(12,'星期六', 322),(16,'星期六', 132),(19,'星期六', 2),(5,'星期六', 3),(3,'星期六', 323)
,(18,'星期日', 65) ,(13,'星期日', 165) ,(1,'星期日', 5) ,(14,'星期日', 665)
) a([hour], [dayname], [hourlysales])
)
SELECT dy.[dayname], hr.[hour] ,FORMAT(DATEADD(hour,hr.[hour],'00:00'),'HH:mm') As formathr
, ISNULL([hourlysales], 0) AS [hourlysales]
FROM cte_hours hr
CROSS JOIN cte_days dy
LEFT OUTER JOIN cte_sales sl ON sl.[hour] = hr.[hour] and sl.[dayname] = dy.[dayname]
ORDER BY dy.daynm, hr.[hour];
希望这对您有所帮助。如果您需要更多帮助,请告诉我。
英文:
As @DaleK indicated an ideal solution would be to use a sort of calendar table with days and hours and use it in the code. Here is a solution using the CTE route you have used :
WITH cte_hours
AS (
SELECT 0 AS [hour]
UNION ALL
SELECT [hour] + 1
FROM cte_hours
WHERE [hour] + 1 < 24)
,cte_days
AS (
SELECT daynm, [dayname]
FROM (
VALUES
(0,'Monday') ,(1,'Tuesday') ,(2,'Wednesday') ,(3,'Thursday') ,(4,'Friday') ,(5,'Saturday') ,(6,'Sunday')
) a(daynm, [dayname])
)
/*Sample sales data set */
, cte_sales
AS (
SELECT [hour], [dayname], [hourlysales]
FROM (
VALUES
(4,'Monday', 100), (14,'Monday', 110), (5,'Monday', 20), (6,'Monday', 10), (21,'Monday', 3),(3,'Monday', 50)
,(11,'Tuesday', 3), (12,'Tuesday', 15), (9,'Tuesday', 155), (2,'Tuesday', 25)
,(12,'Wednesday', 125) ,(14,'Wednesday', 9) ,(11,'Wednesday', 95)
,(13,'Thursday', 42), (23,'Thursday', 342), (6,'Thursday', 123)
,(20,'Friday', 9),(4,'Friday', 93)
,(15,'Saturday', 32),(12,'Saturday', 322),(16,'Saturday', 132),(19,'Saturday', 2),(5,'Saturday', 3),(3,'Saturday', 323)
,(18,'Sunday', 65) ,(13,'Sunday', 165) ,(1,'Sunday', 5) ,(14,'Sunday', 665)
) a([hour], [dayname], [hourlysales])
)
SELECT dy.[dayname], hr.[hour] ,FORMAT(DATEADD(hour,hr.[hour],'00:00'),'HH:mm') As formathr
, ISNULL([hourlysales], 0) AS [hourlysales]
FROM cte_hours hr
CROSS JOIN cte_days dy
LEFT OUTER JOIN cte_sales sl ON sl.[hour] = hr.[hour] and sl.[dayname] = dy.[dayname]
ORDER BY dy.daynm, hr.[hour];
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论