我有一张存储员工交易的表格。身份证刷入并刷出。 列:员工ID,员工姓名,刷卡日期和时间,刷出日期和时间。
我需要一个有效的MS SQL Server查询来获取员工ID以及他们缺席的日期。
(注意:可以创建附加表格以回答问题。)
答案 0 :(得分:7)
正如其他人所说,有一个表存储所有工作日会有所帮助。为简单起见,我们将其命名为business_calendar
,并将所有工作日日期存储在名为DATETIME
的{{1}}列中。由于我不知道您使用的SQL Server版本,我将始终使用working_day
- 所以那些仅代表日期的人将没有时间参与。 This answer有助于在进行比较时咨询如何删除时间部分。
为安全起见,建议只查询没有员工刷入或关闭记录的日期 - 这可能适用于边缘情况,例如员工在午夜之后工作或者可能存在DATETIME
如果由于某种原因,其中一个刷卡或滑出没有注册。
要查找单员工缺席的日期:
NULL
...或者要获取所有员工的列表以及他们缺席的日期,可以使用DECLARE @emp_id INT;
SET @emp_id = 1;
SELECT @emp_id AS employee_id, bc.working_day AS absent_day
FROM business_calendar bc
WHERE NOT EXISTS (
SELECT *
FROM attendance a
WHERE a.employee_id = @emp_id
AND (DATEADD(day, DATEDIFF(day, 0, a.swipe_in), 0) = bc.working_day
OR DATEADD(day, DATEDIFF(day, 0, a.swipe_out), 0) = bc.working_day));
:
CROSS JOIN
当然可以通过SELECT e.id AS employee_id, bc.working_day AS absent_day
FROM business_calendar bc
CROSS JOIN employee e
WHERE NOT EXISTS (
SELECT *
FROM attendance a
WHERE a.employee_id = e.id
AND (DATEADD(day, DATEDIFF(day, 0, a.swipe_in), 0) = bc.working_day
OR DATEADD(day, DATEDIFF(day, 0, a.swipe_out), 0) = bc.working_day));
进一步AND
条件轻松过滤到仅包含员工子集和/或日期。
答案 1 :(得分:0)
根据我所做的假设(只有swipe_in,忽略swipe_out),这应该有效。还假设日期范围是一个月的日期范围。我使用了this生成表格的示例。
DECLARE @StartDate DATETIME
SET @StartDate = DATEADD(Month,-1,GetDate())
Declare @EndDate DATETIME
SET @EndDate = Getdate()
SELECT * From (
SELECT * FROM EmployeeAttendance EA
RIGHT OUTER JOIN (
SELECT DATEADD(DAY, nbr - 1, @StartDate) as CalenderDate
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
) A1 ON (Dateadd(dd,0,Datediff(dd,0,A1.CalenderDate)) = DateAdd(dd,0,Datediff(dd,0,EA.SwipeIn))))A2
WHERE Name IS NULL