2015-10-30 183 views
2

我有一个考勤管理系统,记录每次考勤的开始时间和结束时间。我可以通过从结束时间开始计算开始时间来轻松计算停留时间。计算开始时间和结束时间之间的每小时数

的数据的一个例子是这样的: -

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中计算这个值的方法将会非常惊人。

+2

你介意添加你到目前为止尝试过的查询吗? – Wanderer

+0

SUM()a CASE表达式,如果该人员在相关小时内返回1,则返回1;如果不是,则为0。 –

+0

预期结果的第一列是什么?如果那是一天中的小时,它与样本数据不匹配。如果你需要跨越几天,你还需要一个日期。 –

回答

1

如果您的数据已经存在于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 
+0

感谢您的回答Julien。这里有一些非常好的建议 – stevenk

1

您可以在以下使用UNPIVOT

QUERY

;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 
+0

谁和为什么downvoted没有留下评论? –

+0

Q也一直在? – pnuts

+0

@pnuts MikeD ...有人玩得很开心... –

1

enter image description here

在这张照片下面的单元格包含以下公式/常量

...

F3 ... 01.01.2015 00:00:00

G3 .. 。=F3+TIME(1;0;0) ...复制此权利,直到AC3

F4 ... =IF(AND(F$3>=$D4;F$3<$E4);1;0) ...复制这一权利/直到AC10

F12 ... =SUM(F4:F11) ...复制这个权利,直到AC12

这里的实质是检查用户登录时段是否包含您想要测试的时间点(例如,test_time> = start_time和test_time < end_time)...从而您可以获取哲学信息并且> =和<或>和< =

现在...如果你想要一个日常活动曲线w如果没有对标题中的日期进行硬编码,则只能在标题中将时间与用户登录/日期的时间部分进行比较(如in = date-INT(date)...)

+0

我正要提出一些非常相似的东西 - 但你也提供了一张图表!但我认为应该有六个连续的'5's,而不是三个,然后是两个'4's。 – pnuts

+0

你的图表从8或9变为18.不应该是从7到17,因为它从7:15开始为uid 3?它似乎滑了1小时。 –

+0

图表是一个奖金,而是...但我想如果我正在做这样的事情我希望它呈现在几何...为两个4的让我检查 – MikeD

2

Excel 。对于另一downvote :)

enter image description here

在F3的公式跨,下复制到西装:

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

在F1的公式和整个复制的是:

=SUM(F3:F1000) 
+1

一个非常优雅的解决方案! – MikeD

+0

@MikeD谢谢! (已经有好几次了,OP似乎忽略了我的优惠。)但是我仍然喜欢你提供的可视化。 PS你是否击中了错误的箭头 - 整个这篇文章的投票似乎是相反的:) – pnuts

+1

nope ...我upvoted你的答案,因为我真的很喜欢提取小时只是为了获得(平均)每日档案的想法。 – MikeD

1

......或者甚至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。

+0

@stevenk您是否能够完成这项工作? –

+0

十一而不是十? – pnuts

+0

工作了一个魅力,感谢Excel英雄。这可能是所有建议的最简单的解决方案,但我会选择其中一个基于SQL的解决方案作为回答,因为这样可以节省我首先将数据导入到excel中。 – stevenk

相关问题