2013-01-06 86 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