2013-01-06 57 views
2

我有emp表。考勤表:仅连续3个月的SQL记录

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具有连续3个月不存在无222。

回答

2

我想最简单的就是做一个自我加入表3次,每次加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)。

+0

感谢。但是如何在这里使用这个'+ 1个月'? –

+0

看到小提琴,我改了它,所以它适用于MySQL。如果您正在运行另一台服务器,则必须相应地调整语法。 –

+0

我使用MS SQL。我已添加1个月,缺席日期。但它显示了比实际更多的记录。 –

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 

最后,因为你要缺席的日期 - 而不仅仅是员工号码 - 我找到的第一个和最后一个月使用的窗口功能和使用他们作为过滤器的区别。

+0

非常感谢您的帮助 –

+0

+1 tnx的好教训;) –

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