SQL记录仅连续3个月

时间:2013-01-06 10:03:02

标签: sql sql-server date-arithmetic

我有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个月缺席。

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