创建一个存储过程以从时间表 table 中找出加班的员工
Create a stored procedure to find out employees who has overtime from timesheet table
我在下面的数据库中有这个。 (我不要求完整的代码想法就足够了)
在时间表 table 中,样本数据是这样的:
条件如下:
- 一定要写存储过程
- 状态 "IN" 代表 he/she 进入办公室的时间和 "OUT"
表示 he/she 不在办公室或外出
办公室。
- 每次有人进出时使用
卡,它将进入数据库。所以在同一天,有
对于一个人来说可能是多重来龙去脉。
- 我们需要显示下午 5 点后加班的员工。
- 注意,一个人今天可以登录,明天或之后可以出去。
其间,he/she亦可进可出,不伤
加班
条件对我来说似乎很愚蠢,我可以在设计中使用更好的模式并非常有效地解决它。不过在面试的时候被问过一次,我用了SQL server cursor 但是不满足所有条件。任何人都可以帮助了解如何解决这个问题。
这是我的解决方案示例:
Create PROCEDURE [dbo].[sp_get_over_times]
@officeHours INT = 8
AS
BEGIN
SET NOCOUNT ON;
DECLARE @emp_id VARCHAR(10);
DECLARE @att_date Date = NULL;
DECLARE @att_time SMALLDATETIME = NULL;
DECLARE @status VARCHAR(4) = NULL;
DECLARE @emp_id_2 VARCHAR(10) = NULL;
DECLARE @att_date_2 DATE = NULL;
DECLARE @status_2 VARCHAR(4) = NULL;
DECLARE @att_time_2 SMALLDATETIME = NULL;
DECLARE @duration int = NULL;
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT Emp_id, Att_Date,Att_time
FROM dbo.timesheet
WHERE STATUS = 'IN'
GROUP BY Emp_id, Att_Date,Att_time
OPEN c1
FETCH NEXT FROM c1 INTO @emp_id,@att_date,@att_time
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT TOP 1 @emp_id_2 = Emp_id, @att_date_2 = Att_Date, @att_time_2 = Att_time
FROM dbo.timesheet
WHERE STATUS = 'OUT' AND Emp_id = @emp_id AND Att_Date = @att_date;
IF(@emp_id_2 IS NOT NULL) BEGIN
SET @duration = DATEDIFF(minute,@att_time,@att_time_2);
IF(@duration < 0 ) BEGIN
SET @duration = @duration * -1;
END
IF(@duration > @officeHours) BEGIN
SELECT @emp_id, (@duration- @officeHours) AS 'OverTime';
END
END
SET @emp_id_2 = NULL;
FETCH NEXT FROM c1 INTO @emp_id,@att_date,@att_time
END
CLOSE c1
DEALLOCATE c1
结束
如果可以,我需要澄清一下。虽然必须尽快赶走,但有人应该结束,否则我明天会去取。
最初,如果您从这样的查询开始...
declare @reportend datetime
set @reportend = '20150422'
SELECT outs.emp_id,
outs.att_date,
max(ins.att_time) 'In',
outs.att_time 'Out',
datediff(minute, max(ins.att_time), outs.att_time) 'Mins'
FROM timesheet outs
INNER JOIN timesheet ins
on outs.emp_id = ins.emp_id
and ins.att_time < outs.att_time
and ins.status = 'IN'
WHERE outs.status = 'OUT'
and outs.att_time between dateadd(day,-1,@reportend) and @reportend
group by outs.emp_id, outs.att_date, outs.att_time
您可以开始将 IN 和 OUT 事件配对 - 您甚至可以在 FROM 子句中用方括号括起上述内容,然后按员工对分钟数求和。
但是,如果过了一定时间后您没有看到匹配的 IN 和 OUT 事件对,会发生什么情况?这是您要在数据中单独报告/更正的内容,以便我们可以假设所有对都是完整的吗?
假设您正在查看过去 24 小时的 OUT 时间,上述方法适合通宵工作。
如果有人在 运行 报告时正在工作,您是否愿意在接下来的几天摘要中计算该会话,即当他们注销时,或者您是否需要指定一个截止时间?
您可能想减少他们在午夜的时间,以计算他们通宵工作的每个日期的小时数。请稍微说明一下。
我在下面的数据库中有这个。 (我不要求完整的代码想法就足够了)
在时间表 table 中,样本数据是这样的:
条件如下:
- 一定要写存储过程
- 状态 "IN" 代表 he/she 进入办公室的时间和 "OUT" 表示 he/she 不在办公室或外出 办公室。
- 每次有人进出时使用 卡,它将进入数据库。所以在同一天,有 对于一个人来说可能是多重来龙去脉。
- 我们需要显示下午 5 点后加班的员工。
- 注意,一个人今天可以登录,明天或之后可以出去。
其间,he/she亦可进可出,不伤
加班
条件对我来说似乎很愚蠢,我可以在设计中使用更好的模式并非常有效地解决它。不过在面试的时候被问过一次,我用了SQL server cursor 但是不满足所有条件。任何人都可以帮助了解如何解决这个问题。
这是我的解决方案示例:
Create PROCEDURE [dbo].[sp_get_over_times]
@officeHours INT = 8
AS
BEGIN
SET NOCOUNT ON;
DECLARE @emp_id VARCHAR(10);
DECLARE @att_date Date = NULL;
DECLARE @att_time SMALLDATETIME = NULL;
DECLARE @status VARCHAR(4) = NULL;
DECLARE @emp_id_2 VARCHAR(10) = NULL;
DECLARE @att_date_2 DATE = NULL;
DECLARE @status_2 VARCHAR(4) = NULL;
DECLARE @att_time_2 SMALLDATETIME = NULL;
DECLARE @duration int = NULL;
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT Emp_id, Att_Date,Att_time
FROM dbo.timesheet
WHERE STATUS = 'IN'
GROUP BY Emp_id, Att_Date,Att_time
OPEN c1
FETCH NEXT FROM c1 INTO @emp_id,@att_date,@att_time
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT TOP 1 @emp_id_2 = Emp_id, @att_date_2 = Att_Date, @att_time_2 = Att_time
FROM dbo.timesheet
WHERE STATUS = 'OUT' AND Emp_id = @emp_id AND Att_Date = @att_date;
IF(@emp_id_2 IS NOT NULL) BEGIN
SET @duration = DATEDIFF(minute,@att_time,@att_time_2);
IF(@duration < 0 ) BEGIN
SET @duration = @duration * -1;
END
IF(@duration > @officeHours) BEGIN
SELECT @emp_id, (@duration- @officeHours) AS 'OverTime';
END
END
SET @emp_id_2 = NULL;
FETCH NEXT FROM c1 INTO @emp_id,@att_date,@att_time
END
CLOSE c1
DEALLOCATE c1
结束
如果可以,我需要澄清一下。虽然必须尽快赶走,但有人应该结束,否则我明天会去取。
最初,如果您从这样的查询开始...
declare @reportend datetime
set @reportend = '20150422'
SELECT outs.emp_id,
outs.att_date,
max(ins.att_time) 'In',
outs.att_time 'Out',
datediff(minute, max(ins.att_time), outs.att_time) 'Mins'
FROM timesheet outs
INNER JOIN timesheet ins
on outs.emp_id = ins.emp_id
and ins.att_time < outs.att_time
and ins.status = 'IN'
WHERE outs.status = 'OUT'
and outs.att_time between dateadd(day,-1,@reportend) and @reportend
group by outs.emp_id, outs.att_date, outs.att_time
您可以开始将 IN 和 OUT 事件配对 - 您甚至可以在 FROM 子句中用方括号括起上述内容,然后按员工对分钟数求和。
但是,如果过了一定时间后您没有看到匹配的 IN 和 OUT 事件对,会发生什么情况?这是您要在数据中单独报告/更正的内容,以便我们可以假设所有对都是完整的吗?
假设您正在查看过去 24 小时的 OUT 时间,上述方法适合通宵工作。
如果有人在 运行 报告时正在工作,您是否愿意在接下来的几天摘要中计算该会话,即当他们注销时,或者您是否需要指定一个截止时间?
您可能想减少他们在午夜的时间,以计算他们通宵工作的每个日期的小时数。请稍微说明一下。