【问题标题】:Counting numbers per hour between a start and end time在开始和结束时间之间每小时计算数字
【发布时间】:2015-10-30 12:23:01
【问题描述】:

我有一个考勤管理系统,其中记录了每次考勤的开始和结束时间。我可以通过将开始时间与结束时间分开来轻松计算停留时间。

数据示例如下:-

VisitUID          | AttendeeID   | Start_time              | End_time
0  -----          123  -----     01/01/2015 09:15  -----   01/01/2015 17:15
1  -----          456  -----     01/01/2015 10:45  -----   01/01/2015 16:30
2  -----          753  -----     01/01/2015 08:05  -----   01/01/2015 17:45
3  -----          975  -----     01/01/2015 07:15  -----   01/01/2015 15:05
4  -----          864  -----     01/01/2015 15:55  -----   01/01/2015 16:25
5  -----          246  -----     01/01/2015 16:00  -----   01/01/2015 17:35
6  -----          357  -----     01/01/2015 11:10  -----   01/01/2015 14:55

所以计数应该是这样的(如果我数错了请见谅!):-

07 - 1
08 - 2
09 - 3
10 - 4
11 - 5
12 - 5
13 - 5
14 - 5
15 - 5
16 - 5
17 - 3

我想找出一种方法来计算每小时有多少人在现场以了解现场人数?

系统是 SQL,开始和结束是日期时间值,所以在 SQL 甚至 Excel 中计算它的方法会很棒。

【问题讨论】:

  • 您介意添加您目前尝试过的查询吗?
  • SUM() 一个 CASE 表达式,如果该人在所讨论的时间段内在场,则返回 1,否则返回 0。
  • 预期结果的第一列是什么?如果那是一天中的一个小时,它与示例数据不匹配。如果你需要跨越几天,你还需要一个日期。
  • 只有从 07 到 17 的小时数?

标签: sql-server excel date datetime


【解决方案1】:

Excel。再投反对票:)

F3 中上下复制的公式为:

=--AND(HOUR($C3)<G$2,HOUR($D3)>=F$2)  

F1 中的公式复制过来是:

 =SUM(F3:F1000)

【讨论】:

  • 一个非常优雅的解决方案!
  • 不......我赞成你的回答,因为我真的很喜欢提取时间只是为了获得(平均)每日资料的想法。
【解决方案2】:

如果您的数据已经在 SQL Server 数据库中,则无需将它们导出并导入 Excel。只需几行 SQL 即可完成。如果您更喜欢 Excel,那么上面或下面都有一些不错的选择。

您首先需要一张包含所有可能营业时间的表格:values(7), (8), ... 然后,当此表中的小时在开始日期和结束日期之间时,它可以与您的数据连接。

您的数据:

declare @date table(VisitUID int, AttendeeID int, Start_time datetime, End_time datetime)
Insert Into @date(VisitUID, AttendeeID, Start_time, End_time) values
    (0, 123, '01/01/2015 09:15', '01/01/2015 17:15')
    , (1, 456, '01/01/2015 10:45', '01/01/2015 16:30')
    , (2, 753, '01/01/2015 08:05', '01/01/2015 17:45')
    , (3, 975, '01/01/2015 07:15', '01/01/2015 15:05')
    , (4, 864, '01/01/2015 15:55', '01/01/2015 16:25')
    , (5, 246, '01/01/2015 16:00', '01/01/2015 17:35')
    , (6, 357, '01/01/2015 11:10', '01/01/2015 14:55')

查询:

Select h.n, COUNT(*)
From (values(7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18)) as h(n)
Inner Join @date d on 
    h.n >= DATEPART(hour, d.Start_time) 
    and  h.n <= DATEPART(hour, d.End_time)+1
Group by h.n

如果您需要从 0 到 7 或 18 到 0 的数据,只需将它们添加到列表中:values(6), (7), (8)...(18)...

看来你的计算是正确的。我有相同的输出。

输出:

Hour    Count
7       1
8       2
9       3
10      4
11      5
12      5
13      5
14      5
15      5
16      5
17      3

【讨论】:

  • 感谢朱利安的回答。这里有一些非常好的建议
【解决方案3】:

在这张图片中,以下单元格包含以下公式/常数...

F3 ...01.01.2015 00:00:00

G3 ... =F3+TIME(1;0;0) ... 复制到 AC3 为止

F4 ... =IF(AND(F$3&gt;=$D4;F$3&lt;$E4);1;0) ... 向右/向下复制到 AC10

F12 ... =SUM(F4:F11) ... 复制到 AC12 为止

这里的本质是检查用户登录期间是否“包含”您要测试的时间点(例如 test_time >= start_time AND test_time = 和 和

现在......如果您想要一个每日活动曲线而不在标题中硬编码日期,您可以只在标题中使用时间并将其与用户登录/退出日期的时间部分进行比较(如 =date -INT(日期) ...)

【讨论】:

  • 您的图表从 8 或 9 到 18。它不应该是从 7 到 17,因为它从 7:15 开始为 uid 3?好像时间差了 1 小时。
  • 这个图表是一个额外的奖励......但我想如果我正在做这样的事情,我希望它以图形方式呈现......对于两个 4 让我检查一下
  • @JulienVavasseur 严格来说你是对的......但是我认为 OP 不会禁止用户提前登录并稍后工作......所以我想展示的是一个 抽象 可以在任何白天应用
  • @MikeD 在 7 点之前到 24 点之前没有错。但是根据它的输出和数据,它似乎应该是 7 和 8 之间的 1。在图表上它是 8 和 9 之间的 1 .等等...
  • @pnuts 很好发现 ... 泊位是 VisitUID=4 ... 访问不到一个小时 ... 所以这里的伟大公式达到了它的极限 ggg .. . 思考 ...
【解决方案4】:

您可以在下面使用UNPIVOT

查询

;with cte as
(
select   DATEPART(hh,Start_time) StartTime
       , DATEPART(hh,End_time) EndTime
       , CASE WHEN 7 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1  ELSE 0 END AS [7]
       , CASE WHEN 8 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1  ELSE 0 END AS [8]
       , CASE WHEN 9 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1  ELSE 0 END AS [9]
       , CASE WHEN 10 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [10]
       , CASE WHEN 11 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [11]
       , CASE WHEN 12 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [12]
       , CASE WHEN 13 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [13]
       , CASE WHEN 14 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [14]
       , CASE WHEN 15 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [15]
       , CASE WHEN 16 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [16]
       , CASE WHEN 17 BETWEEN DATEPART(hh,Start_time) AND DATEPART(hh,End_time) THEN 1 ELSE 0 END AS [17]
from #test
)
select StartTime1 StartTime, sum(Cnt) Counter
from(
select StartTime,[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17]
from cte
) p
UNPIVOT
(
    Cnt FOR StartTime1 IN ([7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17])
)AS unpvt
group by StartTime1
order by CAST(StartTIme1 AS INT)

样本数据

create table #test
(
VisitUID   INT,
AttendeeID INT,
Start_time DATETIME,
End_time   DATETIME,
)
insert into #test values
(0, 123,'01/01/2015 09:15','01/01/2015 17:15'),
(1, 456,'01/01/2015 10:45','01/01/2015 16:30'),
(2, 753,'01/01/2015 08:05','01/01/2015 17:45'),
(3, 975,'01/01/2015 07:15','01/01/2015 15:05'),
(4, 864,'01/01/2015 15:55','01/01/2015 16:25'),
(5, 246,'01/01/2015 16:00','01/01/2015 17:35'),
(6, 357,'01/01/2015 11:10','01/01/2015 14:55')

输出

StartTime   Counter
7           1
8           2
9           3
10          4
11          5
12          5
13          5
14          5
15          5
16          5
17          3

【讨论】:

  • OK ... "Jedem Tierchen sein Pläsierchen" ... 我更喜欢享受谜题和回答问题 ggg
  • @JulienVavasseur 你在说什么?我首先在这里投了反对票……之后我投了赞成票。你觉得 unpivot 有什么复杂的地方?
  • @Stanislovas Kalašnikovas 虽然它工作正常,但我只是觉得这包含大量计算和测试,然后在一个查询中进行转换,而要求并不那么复杂。
【解决方案5】:

...甚至 Excel 也会很棒。

假设您的数据在 A:D 列中,选择 11 个连续垂直的单元格并将以下内容粘贴到公式栏中并使用 CONTROL-ENTER 确认:

=SUMPRODUCT((ROWS($1:1)+6>=HOUR(C$2:C$99))*(ROWS($1:1)+6<=HOUR(D$2:D$99)))

注意:如果考勤数据超出第99行,则适当增加公式中的99。

【讨论】:

  • 很有魅力,感谢 Excel Hero。这可能是所有建议中最简单的解决方案,但我会投票给基于 SQL 的解决方案之一作为答案,这样可以节省我首先将数据导入 excel 的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
相关资源
最近更新 更多