如何在两次之间添加每小时计数
Posted
技术标签:
【中文标题】如何在两次之间添加每小时计数【英文标题】:How to add a count per hour between two times 【发布时间】:2019-01-10 16:17:09 【问题描述】:我不确定这是否可行,但我想显示在条目有效的每小时两个日期/时间之间有效的结果:
RcvDateTime FinishDateTime Qty
---------------- ---------------- ---
2019-01-09 22:00 NULL 1
2019-01-10 09:00 2019-01-10 10:10 3
2019-01-10 11:10 2019-01-10 13:10 2
2019-01-10 09:10 2019-01-10 13:25 1
2019-01-10 12:00 2019-01-10 14:15 2
2019-01-10 13:20 NULL 1
如果我在 2019-01-10 15:00 运行查询,我正在寻找的查询结果
Hour Count
---- -----
01 1 (Row 1)
02 1 (Row 1)
03 1 (Row 1)
04 1 (Row 1)
05 1 (Row 1)
06 1 (Row 1)
07 1 (Row 1)
08 1 (Row 1)
09 5 (Rows 1,2,4)
10 5 (Rows 1,2,4)
11 4 (Rows 1,3,4)
12 6 (Rows 1,3,4,5)
13 7 (Rows 1,3,4,5,6)
14 3 (Rows 1,5,6)
我可以获取当前有效的任何行的数据:
SELECT DATEPART(hour,GETDATE()) AS Hour, SUM(Qty) AS Count WHERE FinishDateTime IS NULL
但正在努力寻找一种方法来增加过去的小时数(在 RcvDateTime 和 FinishDateTime 之间。
我们将不胜感激地接受任何想法、提示,或者即使这是可能的。
【问题讨论】:
不应该FinishDateTime
来 RcvDateTime
吗?
是的,抱歉,在我的示例中,07 应该是 10。
【参考方案1】:
如果我了解您的全部查询,我认为 CTE 和使用 group by 的右连接查询可能会降低您的例外结果。
看看这个相关的例子:
CREATE TABLE #MyTable
(PrimaryKey int PRIMARY KEY,
DateValueBegin DATETIME,
DateValueEnd DATETIME,
NbValue int
);
GO
INSERT INTO #MyTable
SELECT 1, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 2
UNION
SELECT 2, DATEADD(HOUR,-2,GETDATE()), DATEADD(HOUR,-1,GETDATE()), 4
UNION
SELECT 3, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 3
UNION
SELECT 4, DATEADD(HOUR,-1,GETDATE()), NULL, 2
UNION
SELECT 5, DATEADD(HOUR,-1,GETDATE()), NULL, 2;
with mycte as
(
SELECT 0 AS MyHour
UNION ALL
SELECT MyHour + 1
FROM mycte
WHERE MyHour + 1 < 24
)
SELECT convert(date, DateValueBegin) AS 'DAY' , MyHour AS 'Hour', SUM(NbValue)
FROM #MyTable right join mycte on (DATEPART(HOUR,DateValueBegin) <= MyHour AND (DateValueEnd IS NULL OR DATEPART(HOUR,DateValueEnd) >= MyHour))
Group By convert(date, DateValueBegin), MyHour;
DROP TABLE #MyTable
我有更新代码来使用间隔日期
结果:
DAY Hour Total
NULL 12 NULL
NULL 13 NULL
NULL 14 NULL
2019-01-10 15 9
2019-01-10 16 13
2019-01-10 17 9
2019-01-10 18 4
2019-01-10 19 4
2019-01-10 20 4
2019-01-10 21 4
2019-01-10 22 4
2019-01-10 23 4
编辑以获取现有日期
CREATE TABLE #MyTable
(PrimaryKey int PRIMARY KEY,
DateValueBegin DATETIME,
DateValueEnd DATETIME,
NbValue int
);
GO
INSERT INTO #MyTable
SELECT 1, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 2
UNION
SELECT 2, DATEADD(HOUR,-2,GETDATE()), DATEADD(HOUR,-1,GETDATE()), 4
UNION
SELECT 3, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 3
UNION
SELECT 4, DATEADD(HOUR,-1,GETDATE()), NULL, 2
UNION
SELECT 5, DATEADD(HOUR,-1,GETDATE()), NULL, 2
UNION
SELECT 6, DATEADD(DAY,-1,GETDATE()), DATEADD(HOUR,1,DATEADD(DAY,-1,GETDATE())), 2
UNION
SELECT 7, DATEADD(DAY,-1,GETDATE()), DATEADD(HOUR,3,DATEADD(DAY,-1,GETDATE())), 2;
with mycte as
(
SELECT 0 AS MyHour
UNION ALL
SELECT MyHour + 1
FROM mycte
WHERE MyHour + 1 < 24
)
SELECT convert(date, ISNULL(DateValueBegin,MyDay)) AS 'DAY' , MyHour AS 'Hour', SUM(ISNULL(NbValue,0)) AS TOTAL
FROM #MyTable
right join(select distinct convert(date, DateValueBegin) MyDay, MyHour from mycte, #MyTable) AS SubDayHour on (DATEPART(HOUR,DateValueBegin) <= MyHour AND ((DateValueEnd IS NULL AND MyHour < DATEPART(HOUR,GETDATE())) OR DATEPART(HOUR,DateValueEnd) >= MyHour)) AND convert(date, DateValueBegin) = MyDay
Group By convert(date, ISNULL(DateValueBegin,MyDay)), MyHour
ORDER BY convert(date, ISNULL(DateValueBegin,MyDay)) ASC, MyHour ASC;
SELECT * FROM #MyTable ;
DROP TABLE #MyTable
新结果:
DAY Hour TOTAL
2019-01-10 0 0
2019-01-10 1 0
2019-01-10 2 0
2019-01-10 3 0
2019-01-10 4 0
2019-01-10 5 0
2019-01-10 6 0
2019-01-10 7 0
2019-01-10 8 0
2019-01-10 9 0
2019-01-10 10 0
2019-01-10 11 4
2019-01-10 12 4
2019-01-10 13 2
2019-01-10 14 2
2019-01-10 15 0
2019-01-10 16 0
2019-01-10 17 0
2019-01-10 18 0
2019-01-10 19 0
2019-01-10 20 0
2019-01-10 21 0
2019-01-10 22 0
2019-01-10 23 0
2019-01-11 0 0
2019-01-11 1 0
2019-01-11 2 0
2019-01-11 3 0
2019-01-11 4 0
2019-01-11 5 0
2019-01-11 6 0
2019-01-11 7 0
2019-01-11 8 0
2019-01-11 9 9
2019-01-11 10 13
2019-01-11 11 5
2019-01-11 12 0
2019-01-11 13 0
2019-01-11 14 0
2019-01-11 15 0
2019-01-11 16 0
2019-01-11 17 0
2019-01-11 18 0
2019-01-11 19 0
2019-01-11 20 0
2019-01-11 21 0
2019-01-11 22 0
2019-01-11 23 0
【讨论】:
完美谢谢,正是我所追求的。我从未想过以这种方式使用 CTE。 嗨 Pascal,我遇到了另一个问题,有时我的 DateValueBegin 日期会是前一天,例如:我今天可以运行报告,但 DateValueBegin 可能是 '2019-01-10 06: 05:09.580' 今天的 DateValueEnd 或 NULL 我希望计数在今天的 DAY 中,而不是显示昨天。这有意义吗? @Ben 是的,我会以另一种方式看待这个 我更新了我的示例,希望能更好地解释我的意思,包括前一天。因此 DAY 将仅显示今天的日期,但包括仍然具有 DateValueEnd 为 NULL 或当前日期的任何条目的计数。因此,您只会返回 24 行(24 小时),但无论之前的 DateValueBegin 是什么,都将包含任何仍然有效的内容。【参考方案2】:试试这个,如果您需要不同的组,只需更改日期即可。此外,如果您只想要日期跨度,请为此添加 where 子句。
SELECT CAST(FinishDateTime as date) AS ForDate,
DATEPART(hour,FinishDateTime) AS OnHour,
SUM(QTY) AS SumPerTimeGroup
FROM YourTable
GROUP BY CAST(FinishDateTime as date),
DATEPART(hour,FinishDateTime)
【讨论】:
以上是关于如何在两次之间添加每小时计数的主要内容,如果未能解决你的问题,请参考以下文章