2017-09-22 2 views
1

j'ai une source de données qui a swipe employé/dans le format suivantrequêtes SQL pour transposent début et de finition en bons jours

+----------+---------+-----------+------------+-------+-----------+ 
| Forename | Surname | Clock_Num | Date  | Time | Direction | 
+----------+---------+-----------+------------+-------+-----------+ 
| John  | Kerry | 0111  | 2017-09-21 | 18:00 | IN  | 
+----------+---------+-----------+------------+-------+-----------+ 
| John  | Kerry | 0111  | 2017-09-22 | 02:00 | OUT  | 
+----------+---------+-----------+------------+-------+-----------+ 
| Bill  | Long | 0112  | 2017-09-21 | 10:00 | IN  | 
+----------+---------+-----------+------------+-------+-----------+ 
| Bill  | Long | 0112  | 2017-09-21 | 18:00 | OUT  | 
+----------+---------+-----------+------------+-------+-----------+ 
| George | Takai | 0113  | 2017-09-22 | 11:00 | IN  | 
+----------+---------+-----------+------------+-------+-----------+ 

Maintenant, je veux voir ces presque transposée à un seul enregistrement par employé en fonction de l'heure de début de poste comme si

+----------+---------+-----------+------------+------------------+------------------+ 
| Forename | Surname | Clock_Num | Shift Date | Time In   | Time Out   | 
+----------+---------+-----------+------------+------------------+------------------+ 
| John  | Kerry | 0111  | 2017-09-21 | 2017-09-21 18:00 | 2017-09-22 02:00 | 
+----------+---------+-----------+------------+------------------+------------------+ 
| Bill  | Long | 0112  | 2017-09-22 | 2017-09-22 10:00 | 2017-09-22 18:00 | 
+----------+---------+-----------+------------+------------------+------------------+ 
| George | Takai | 0113  | 2017-09-22 | 2017-09-22 11:00 | Null    | 
+----------+---------+-----------+------------+------------------+------------------+ 

La partie qui m'a bloqué est la logique de la requête. Par exemple, s'il n'y a pas d'heure de sortie de l'horloge supérieure à l'heure de l'horloge d'un seul jour, puis à la sortie suivante, mais avant la prochaine entrée (si l'employé oublie de sortir), affichez comme nul

Quelqu'un peut-il m'aider ou me diriger dans la bonne direction?

J'accepte, il ne peut pas être une réponse simple 2-3 ligne à cela, il a juste besoin d'être relativement efficace en raison de volume important de dossiers

+0

Bill Long a deux calor ... Étiez-vous au courant de cela? –

+0

En outre, vous devez afficher plus de données, par ex. que se passe-t-il si une personne a plus d'un événement IN/OUT. –

+0

@TimBiegeleisen Corrigé, merci. –

Répondre

2

en utilisant un common table expression ainsi que la fonction de fenêtre lead() pour obtenir le Next_Time et cross apply() pour obtenir le prochain Time 'out' qui est après Time 'dans', mais avant le Next_Time 'dans':

;with cte as (
    select Forename, Surname, Clock_Num, Direction, Date 
    , Time = convert(datetime,t.Date)+convert(datetime,t.Time) 
    , Next_Time = lead(convert(datetime,t.Date)+convert(datetime,t.Time)) 
     over (partition by Forename, Surname, Clock_Num, Direction 
       order by Date, Time) 
    from t 
) 
select t.Forename, t.Surname, t.Clock_Num, t.Date 
    , Time_In = t.Time 
    , Time_Out = x.Time 
from cte as t 
    outer apply (
    select top 1 
     o.Time 
    from cte as o 
    where o.Forename = t.Forename 
     and o.Surname = t.Surname 
     and o.Clock_Num = t.Clock_Num 
     and o.Direction = 'OUT' 
     and o.Time > t.Time 
     and (o.Time < t.Next_Time or t.Next_Time is null) 
     order by o.Time 
) as x 
where t.Direction = 'IN' 
order by clock_num 

rextester démo: http://rextester.com/UIMJ36919

retours:

+----------+---------+-----------+------------+---------------------+---------------------+ 
| Forename | Surname | Clock_Num | Date |  Time_In  |  Time_Out  | 
+----------+---------+-----------+------------+---------------------+---------------------+ 
| John  | Kerry |  111 | 2017-09-21 | 2017-09-21 18:00:00 | 2017-09-22 02:00:00 | 
| Bill  | Long |  112 | 2017-09-21 | 2017-09-21 10:00:00 | 2017-09-21 18:00:00 | 
| George | Takai |  113 | 2017-09-22 | 2017-09-22 11:00:00 | NULL    | 
+----------+---------+-----------+------------+---------------------+---------------------+ 

Pour 2008, vous pouvez utiliser outer apply() pour simuler lead() comme ceci:

;with cte as (
    select Forename, Surname, Clock_Num, Direction, Date 
    , Time = convert(datetime,t.Date)+convert(datetime,t.Time) 
    , x.Next_Time 
    from t 
    outer apply (
     select top 1 
     Next_Time = convert(datetime,o.Date)+convert(datetime,o.Time) 
     from t as o 
     where o.Forename = t.Forename 
     and o.Surname = t.Surname 
     and o.Clock_Num = t.Clock_Num 
     and o.Direction = t.Direction 
     and ((o.Date = t.Date and o.Time > t.Time) 
      or o.Date > t.Date) 
     order by o.Date, o.Time 
) as x 
) 
select t.Forename, t.Surname, t.Clock_Num, t.Date 
    , Time_In = t.Time 
    , Time_Out = x.Time 
from cte as t 
    outer apply (
    select top 1 
     o.Time 
    from cte as o 
    where o.Forename = t.Forename 
     and o.Surname = t.Surname 
     and o.Clock_Num = t.Clock_Num 
     and o.Direction = 'OUT' 
     and o.Time > t.Time 
     and (o.Time < t.Next_Time or t.Next_Time is null) 
     order by o.Time 
) as x 
where t.Direction = 'IN' 
order by clock_num 

rextester demo:

+0

Salut Merci pour la réponse, j'ai utilisé votre réponse, mais je reçois un "Les fonctionnalités de Parallel Data Warehouse (PDW) ne sont pas activées." Message et malheureusement pas votre exemple réponse ... Je n'ai pas traité PDW avant ... est-ce quelque chose que je peux activer dans SSMS2012 ou une installation séparée? –

+0

Ahh bien que la version cible soit 2012 le serveur dev m'a été attribué en 2008 donc le Lead ne fonctionne pas ... Je peux demander un serveur de développement différent mais juste un contrôle y at-il une autre façon de faire en 2008? –

+0

@LRiley Mis à jour avec la version 2008 – SqlZim