2013-01-06 3 views
2

J'ai une table pour emp. feuille de présence:Enregistrements SQL seulement pour 3 mois consécutifs

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 

je dois retourner les lignes comme ci-dessous:

emp_No Absent_Date 
------------------- 
222  13/02/2012 
222  01/03/2012 
222  02/03/2012 
222  29/04/2012 

parce que emp n ° 222 ayant absent 3 mois consécutifs.

Répondre

2

Je suppose que l'est plus facile à faire une jointure réflexive de la table trois fois, à chaque fois que l'ajout d'1 mois à compter de la date:

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) 

Cela vous donnera tous les emp_No uniques « s. Maintenant, pour obtenir le résultat que vous voulez, vous devrez faire une autre JOIN (respectivement je vais utiliser IN pour faciliter la lecture):

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) 
) 

Voir la SQL Fiddle d'essayer (je devais changer le mois en ajoutant la syntaxe de SQL standard à MySQL).

+0

Merci. Mais comment utiliser ce '+ 1 MOIS' ici? –

+0

Voir le violon, je l'ai changé là-bas, donc cela fonctionne avec MySQL. Si vous utilisez un autre serveur, vous devrez adapter la syntaxe en conséquence. –

+0

J'utilise MS SQL. J'ai ajouté 1 mois avec la date d'absence. Mais il montre plus d'enregistrements que réels. –

3

Ce que vous essayez de faire est de regrouper les absences par mois consécutifs. Laissez-moi supposer que vous utilisez une base de données raisonnable qui prend en charge la fonction dense_rank() et les fonctions de la fenêtre de base.

L'idée est de trouver des mois en séquence qui ont des absences. Ensuite, comptez le nombre de mois dans chaque séquence pour chaque employé et gardez ceux qui ont plus de trois mois.

La requête le fait en convertissant le mois en un nombre de mois - 12 fois l'année plus le mois. Il utilise ensuite une observation simple. Le numéro du mois moins une séquence de nombres est une constante, pour des mois consécutifs. Habituellement, j'utilise row_number() pour la séquence. Parce que vous avez des absences en double dans un mois, j'utilise 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 

Enfin, parce que vous voulez que les dates absents - par opposition aux seuls chiffres des employés - je trouve le premier et le dernier mois en utilisant des fonctions de fenêtre et d'utiliser leur différence comme un filtre.

+0

Merci beaucoup pour votre aide –

+0

+1 tnx pour une bonne leçon;) –

0

Essayez de ce code:

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 
Questions connexes