4

我有 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

因为只有 emp 222 连续 3 个月缺席。

4

3 回答 3

5

您要做的是按连续月份对缺勤进行分组。让我假设您正在使用支持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

最后,因为您想要缺勤日期——而不仅仅是员工人数——我使用窗口函数找到第一个月和最后一个月,并将它们的差异用作过滤器。

于 2013-01-06T15:41:58.230 回答
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)。

于 2013-01-06T10:09:37.750 回答
1

试试这个代码:

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
于 2013-01-08T10:10:37.820 回答