如何在两次之间添加每小时计数

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)

【讨论】:

以上是关于如何在两次之间添加每小时计数的主要内容,如果未能解决你的问题,请参考以下文章

如果在两次之间,如何从另一个表返回值?

SQL - OVER 子句范围在 2 次之间

我如何使用 mysql 选择查询在“x 小时 y 分钟 z 秒”之类的词中获得 2 次之间的差异

在 SQL 中搜索两次之间的变量

java中两次之间小时的正确格式

如何使此查询也返回计数值为 0 的行?