我目前有一个员工记录sql表有3列
fromState: String
,
toState: String
,
timestamp: DateTime
fromState
可以是In
或Out
。 In
表示员工进来,Out
表示员工出去了。每行只能从In
转换为Out
或Out
转换为In
。
我想在sql中生成一个临时表,以便在给定的小时(小时,小时)内跟踪,公司中有多少员工。 Aka,结果表包含HourBucket
,NumEmployees
列。
在非SQL代码中,我可以通过将numEmployees
初始化为0
并逐行查看表(按timestamp
排序)并添加(员工进来)来完成此操作或减去(去掉)到numEmployees
(按timestamp
小时划分)。
我对如何在SQL中执行此操作毫无头绪。有线索吗?
答案 0 :(得分:0)
使用COUNT ... GROUP BY
查询。但是,从您的描述中看不到您使用的状态了!另外,假设您有一个employeeID字段。
E.g。
SELECT fromState AS 'Status', COUNT(*) AS 'Number'
FROM StaffinBuildingTable
INNER JOIN (SELECT employeeID AS 'empID', MAX(timestamp) AS 'latest' FROM StaffinBuildingTable GROUP BY employeeID) AS LastEntry ON StaffinBuildingTable.employeeID = LastEntry.empID
GROUP BY fromState
LastEntry子查询将生成一个employeeID列表,该列表仅限于每位员工的上一个时间戳。
INNER JOIN会将主表限制为只与双方匹配的employeeID。
外部GROUP BY产生计数。
SELECT HOUR(SBT.timestamp) AS 'Hour', SBT.fromState AS 'Status', COUNT(*) AS 'Number'
FROM StaffinBuildingTable AS SBT
INNER JOIN (
SELECT SBIJ.employeeID AS 'empID', MAX(timestamp) AS 'latest'
FROM StaffinBuildingTable AS SBIJ
WHERE DATE(SBIJ.timestamp) = CURDATE()
GROUP BY SBIJ.employeeID) AS LastEntry ON SBT.employeeID = LastEntry.empID
GROUP BY SBT.fromState, HOUR(SBT.timestamp)
将CURDATE()替换为您感兴趣的日期。
请注意,这不是最佳的,因为它会计算两次HOUR - 一次是数据,一次是组。
您再次使用INNER JOIN来限制返回的行数,这次是指定日期的最后一个时间戳。
答案 1 :(得分:0)
对我而言,您对FromState
和ToState
的描述似乎是错误的方式,我希望基于ToState
执行此操作。但是假设我错了,以下内容应该指向正确的方向:
首先,我创建一个"数字"每天每小时包含24行的表格:
create table tblHours
(Number int);
insert into tblHours values
(0),(1),(2),(3),(4),(5),(6),(7),
(8),(9),(10),(11),(12),(13),(14),(15),
(16),(17),(18),(19),(20),(21),(22),(23);
然后,对于员工日志记录表中的每个日期,我在另一个新表中创建一行以包含您的计数:
create table tblDailyHours
(
HourBucket datetime,
NumEmployees int
);
insert into tblDailyHours (HourBucket, NumEmployees)
select distinct
date_add(date(t.timeStamp), interval h.Number HOUR) as HourBucket,
0 as NumEmployees
from
tblEmployeeLogging t
CROSS JOIN tblHours h;
然后我更新此表以包含所有相关计数:
update tblDailyHours h
join
(select
h2.HourBucket,
sum(case when el.fromState = 'In' then 1 else -1 end) as cnt
from
tblDailyHours h2
join tblEmployeeLogging el on
h2.HourBucket >= el.timeStamp
group by h2.HourBucket
) cnt ON
h.HourBucket = cnt.HourBucket
set NumEmployees = cnt.cnt;
您现在可以使用
检索计数select *
from tblDailyHours
order by HourBucket;
计数会在显示的每个时间点显示网站上的数字,如果您想在所涉及的小时内,我们需要调整此数据小。
此代码有一个工作版本(在日志记录表中使用的不是非常现实的数据):rextester.com/DYOR23344
原始答案(基于所有统计数据)
如果您乐意搜索所有行,并希望获得当前的人数"你可以用这个:
select
sum(case when t.FromState = 'In' then 1 else -1) as Heads
from
MyTable t
但是如果你知道在午夜总会有一个人没有人,你可以添加一个where子句来阻止它查看比它需要更多的行:
where
date(t.timestamp) = curdate()
同样,假设人头数在午夜时间达到零,您可以随意推广该方法以获得人数,如下所示:
where
date(t.timestamp) = "CENSUS DATE" AND
t.timestamp <= "CENSUS DATETIME"
显然,您需要使用返回感兴趣的日期和日期时间的代码替换我引用的字符串。如果员工人数在午夜没有返回零,您可以通过删除where
子句的第一行来实现相同目的。