我有emp表。出勤表:
emp_No Absent_Date
-------------------
111 01/03/2012
111 05/05/2012
222 13/02/2012
222 01/03/2012
222 02/03/2012
222 29/04/2012
222 09/09/2012
333 15/05/2012
333 18/09/2012
333 19/09/2012
我需要返回如下所示的行:
emp_No Absent_Date
-------------------
222 13/02/2012
222 01/03/2012
222 02/03/2012
222 29/04/2012
因为只有没有222连续3个月缺席。
答案 0 :(得分:3)
您要做的是将连续几个月分组。我假设您正在使用支持dense_rank()
函数和基本窗口函数的合理数据库。
这个想法是按顺序找出有缺席的月份。然后,计算每个员工每个序列中的月数,并保留那些超过三个月的员工。
查询通过将月份转换为月份数量来实现此目的 - 年份的12倍加上月份。然后使用简单的观察。连续几个月,月份数减去一系列数字是一个常数。通常,我使用row_number()
作为序列。因为您在一个月内有重复缺席,所以我使用的是dense_rank()
。
select emp_no, absent_date
from (select a.*,
max(monthnum) over (partition by emp_no, groupnum) as lastmonth,
min(monthnum) over (partition by emp_no, groupnum) as firstmonth
from (select a.*,
monthnum - dense_rank() over (partition by emp_no order by monthnum) as groupnum
from (select a.*,
year(a.absent_date)*12+month(a.absent_date) as monthnum
from Attendance a
) a
) a
) a
where lastmonth - firstmonth >= 2
最后,因为你想要缺席的日期 - 而不仅仅是雇员号码 - 我找到使用窗口函数的第一个月和最后一个月,并将它们的差异用作过滤器。
答案 1 :(得分:2)
我想最简单的方法是自动加入桌子三次,每次加1个月到日期:
SELECT DISTINCT S1.emp_No
FROM attendance_sheet S1
JOIN attendance_sheet S2
ON S1.emp_No = S2.emp_No
AND Month(S1.Absent_Date + 1 MONTH) = Month(S2.Absent_Date)
AND Year(S1.Absent_Date + 1 MONTH) = Year(S2.Absent_Date)
JOIN attendance_sheet S3
ON S2.emp_No = S3.emp_No
AND Month(S2.Absent_Date + 1 MONTH) = Month(S3.Absent_Date)
AND Year(S2.Absent_Date + 1 MONTH) = Year(S3.Absent_Date)
这将为您提供所有独特的emp_No
。现在要获得你想要的结果,你将不得不做另一次加入(我将使用IN
来更容易阅读):
SELECT *
FROM attendance_sheet
WHERE emp_No IN (
SELECT S1.emp_No
FROM attendance_sheet S1
JOIN attendance_sheet S2
ON S1.emp_No = S2.emp_No
AND Month(S1.Absent_Date + 1 MONTH) = Month(S2.Absent_Date)
AND Year(S1.Absent_Date + 1 MONTH) = Year(S2.Absent_Date)
JOIN attendance_sheet S3
ON S2.emp_No = S3.emp_No
AND Month(S2.Absent_Date + 1 MONTH) = Month(S3.Absent_Date)
AND Year(S2.Absent_Date + 1 MONTH) = Year(S3.Absent_Date)
)
请参阅SQL Fiddle尝试(我必须将月份添加语法从标准SQL更改为MySQL)。
答案 2 :(得分:0)
尝试此代码:
SELECT DISTINCT * FROM
(
SELECT E1.Attendance _No,
E1.Absent_Date
FROM Attendance E1
JOIN Attendance E2
ON E2.Attendance _No = E1.Attendance _No
AND MONTH(E2.Absent_Date) = MONTH(E1.Absent_Date) + 1
JOIN Attendance E3
ON E3.Attendance _No = E2.Attendance _No
AND MONTH(E3.Absent_Date) = MONTH(E2.Absent_Date) + 1
UNION ALL
SELECT E2.Attendance _No,
E2.Absent_Date
FROM Attendance E1
JOIN Attendance E2
ON E2.Attendance _No = E1.Attendance _No
AND MONTH(E2.Absent_Date) = MONTH(E1.Absent_Date) + 1
JOIN Attendance E3
ON E3.Attendance _No = E2.Attendance _No
AND MONTH(E3.Absent_Date) = MONTH(E2.Absent_Date) + 1
UNION ALL
SELECT E3.Attendance _No,
E3.Absent_Date
FROM Attendance E1
JOIN Attendance E2
ON E2.Attendance _No = E1.Attendance _No
AND MONTH(E2.Absent_Date) = MONTH(E1.Absent_Date) + 1
JOIN Attendance E3
ON E3.Attendance _No = E2.Attendance _No
AND MONTH(E3.Absent_Date) = MONTH(E2.Absent_Date) + 1
) A