Sql 计算员工时间表数据
假设您有一个时钟表,每个时钟事件只有一个时间戳条目:Sql 计算员工时间表数据,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,假设您有一个时钟表,每个时钟事件只有一个时间戳条目: Userid CheckTime 312 2018-05-08 05:52:00 312 2018-05-08 18:06:00 312 2018-05-10 05:55:00 312 2018-05-10 18:00:00 312 2018-05-11 05:58:00 312 2018-05-11 18:00:00 312 2018-05-12 05:35:00 312 2
Userid CheckTime
312 2018-05-08 05:52:00
312 2018-05-08 18:06:00
312 2018-05-10 05:55:00
312 2018-05-10 18:00:00
312 2018-05-11 05:58:00
312 2018-05-11 18:00:00
312 2018-05-12 05:35:00
312 2018-05-12 18:00:00
如何统计SQL Server中的事件以显示为这样
Day Date In Out Reg OT
Tuesday 5/8/2018 5:52AM 6:06PM 12.00 0.00
Thursday 5/10/2018 5:55AM 6:00PM 12.00 0.00
Friday 5/11/2018 5:58AM 6:00PM 12.00 0.00
Saturday 5/12/2018 5:35AM 6:00PM 12.00 0.42
此外,我们有夜班人员,他们一天开始轮班,另一天继续轮班
我不知道该如何计算,因为它是基于行的还是基于列的
我已经试过了…但它不能正常工作
;WITH emp
AS (SELECT [UserID],
[CheckTime],
CAST([CheckTime] AS DATE) AS [Day],
Row_Number()
OVER( PARTITION BY [UserID], CAST([CheckTime] AS DATE)
ORDER BY [UserID], [CheckTime]) AS [RowNumber]
FROM [dbo].[Clock_Data] WHERE CHECKTIME
BETWEEN '2018-05-06' AND '2018-05-13')
SELECT
t1.[UserID],
E.[Last Name]AS [EMPID],
MIN(t1.[CheckTime]) AS [time_in],
MAX(t2.[CheckTime]) AS [time_out],
CAST((SUM(ISNULL(DATEDIFF(ss, t1.[CheckTime],
t2.[CheckTime]) , 0)) / 3600)-1 AS VARCHAR(10)) + '.' +
FROM emp AS t1
LEFT JOIN emp AS t2
ON ( t1.[UserID] = t2.[UserID]
AND t1.[Day] = t2.[Day]
AND t1.[RowNumber] = ( t2.[RowNumber] - 1 )
AND t2.[RowNumber] % 2 = 0
)
INNER JOIN Employees as E on t1.Userid = E.[ID Number]
GROUP BY t1.[UserID], E.[Last Name]
ORDER BY t1.[UserID]
如上所述,这种类型的查询有很多复杂性。漏打/重复打孔。夏时制。假日,周末。对于您需要的任何规则,可以算作O/T的类型。但是对于像您这样一组干净的数据,您可以相当容易地完成这项工作。这决不是一个完整的解决方案,因为你有很多事情需要解决。但这应该是一个不错的起点
declare @Something table
(
Userid int
, CheckTime datetime
)
insert @Something values
(312, '2018-05-08 05:52:00')
, (312, '2018-05-08 18:06:00')
, (312, '2018-05-10 05:55:00')
, (312, '2018-05-10 18:00:00')
, (312, '2018-05-11 05:58:00')
, (312, '2018-05-11 18:00:00')
, (312, '2018-05-12 05:35:00')
, (312, '2018-05-12 18:00:00');
with OrderedResults as
(
select *
, RowNum = ROW_NUMBER() over(partition by Userid order by CheckTime)
from @Something
)
, InPunch as
(
select *
, GroupNum = Row_Number () over(partition by Userid order by RowNum)
from OrderedResults
where RowNum % 2 = 1
)
, OutPunch as
(
select *
, GroupNum = Row_Number () over(partition by Userid order by RowNum)
from OrderedResults
where RowNum % 2 = 0
)
select ip.Userid
, PunchDate = convert(date, ip.CheckTime)
, CheckIn = ip.CheckTime
, CheckOut = op.CheckTime
from InPunch ip
join OutPunch op on op.GroupNum = ip.GroupNum
如上所述,这种类型的查询有很多复杂性。漏打/重复打孔。夏时制。假日,周末。对于您需要的任何规则,可以算作O/T的类型。但是对于像您这样一组干净的数据,您可以相当容易地完成这项工作。这决不是一个完整的解决方案,因为你有很多事情需要解决。但这应该是一个不错的起点
declare @Something table
(
Userid int
, CheckTime datetime
)
insert @Something values
(312, '2018-05-08 05:52:00')
, (312, '2018-05-08 18:06:00')
, (312, '2018-05-10 05:55:00')
, (312, '2018-05-10 18:00:00')
, (312, '2018-05-11 05:58:00')
, (312, '2018-05-11 18:00:00')
, (312, '2018-05-12 05:35:00')
, (312, '2018-05-12 18:00:00');
with OrderedResults as
(
select *
, RowNum = ROW_NUMBER() over(partition by Userid order by CheckTime)
from @Something
)
, InPunch as
(
select *
, GroupNum = Row_Number () over(partition by Userid order by RowNum)
from OrderedResults
where RowNum % 2 = 1
)
, OutPunch as
(
select *
, GroupNum = Row_Number () over(partition by Userid order by RowNum)
from OrderedResults
where RowNum % 2 = 0
)
select ip.Userid
, PunchDate = convert(date, ip.CheckTime)
, CheckIn = ip.CheckTime
, CheckOut = op.CheckTime
from InPunch ip
join OutPunch op on op.GroupNum = ip.GroupNum
这类查询比表面上看起来要复杂得多,我们提供给您的任何查询都需要对它有相同的理解才能维护它。需要考虑的事项:遗漏的打孔、意外的双打孔和为避免打孔而进行的节流、跨越日边界的打孔以及夏时制转换期间时钟位置的持续时间计算,根据时钟位置是否与服务器同步时间,用于加班和正常工作时间计算的特定于域的业务逻辑,等等。我建议将其分成几个较小的部分,并使用利用这些功能的函数和视图,然后在此基础上构建一个更易于管理的查询或过程。有一些东西可以限制不同的打孔,有一些东西可以在打孔之后填充缺少的打孔,有一些东西可以将打孔分类为输入或输出,有一些东西可以在打孔之后考虑夏令时,有一些东西可以包括你的业务逻辑来计算之后的费率,等等,然后有一个视图或过程来使用所有这些。请记住,如果对数据进行了追溯性修改,则可能需要重新运行。这实际上是由一个时钟系统来维持的。时钟数据被拉出,这将确保时钟进入/时钟退出状态。这种查询比表面上看起来要复杂得多,我们给你的任何查询都需要对它有相同的理解才能维护它。需要考虑的事项:遗漏的打孔、意外的双打孔和为避免打孔而进行的节流、跨越日边界的打孔以及夏时制转换期间时钟位置的持续时间计算,根据时钟位置是否与服务器同步时间,用于加班和正常工作时间计算的特定于域的业务逻辑,等等。我建议将其分成几个较小的部分,并使用利用这些功能的函数和视图,然后在此基础上构建一个更易于管理的查询或过程。有一些东西可以限制不同的打孔,有一些东西可以在打孔之后填充缺少的打孔,有一些东西可以将打孔分类为输入或输出,有一些东西可以在打孔之后考虑夏令时,有一些东西可以包括你的业务逻辑来计算之后的费率,等等,然后有一个视图或过程来使用所有这些。请记住,如果对数据进行了追溯性修改,则可能需要重新运行。这实际上是由一个时钟系统来维持的。时钟数据被拉出,这将确保时钟进入/时钟退出状态。没有重拳,是的,我不确定这是否是一个好的起点……Userid PunchDate
code ID PunchDate签入签出2012-04-25 2012-04-25 12:05:00 2012-04-25 13:02:00 2012-04-25 2012-04-25 12:05:00 2012-04-26 12:03:00 2012-04-25 2012-04-04-25 12:05:00 2012-04-25 14:22:00 2012-04-25 2012-04-04-04-25 12:05:00 2012-04-2617:09:00
@edwardhoades-注释不适合格式化,也不确定数据试图显示什么。我很好奇为什么你认为这不是一个好的起点。它返回的数据行与OP请求的数据行相同。我只是没有包括DATEDIFF部分是的,我不确定这是否是一个好的起点……Userid PunchDatecode ID PunchDate签入签出2012-04-25 2012-04-25 12:05:00 2012-04-25 13:02:00 2012-04-25 2012-04-25 12:05:00 2012-04-26 12:03:00 2012-04-25 2012-04-04-25 12:05:00 2012-04-25 14:22:00 2012-04-25 2012-04-04-04-25 12:05:00 2012-04-2617:09:00
@edwardhoades-注释不适合格式化,也不确定数据试图显示什么。我很好奇为什么你认为这不是一个好的起点。它返回的数据行与OP请求的数据行相同。我只是没有包括DATEDIFF部分。