2009-07-28 6 views
0

Par exemple, j'ai une MIS tâche, les données sont:Comment utiliser Linq To Sql pour compter la durée de fonctionnement inactive en un jour?

Id Tâche utilisateur TaskStartTime TaskFinishTime

1 Mike Task1 2009-07-28 09:00:00 2009-07-28 09:45: 00

2 Mike task2 2009-07-28 09:30:00 2009-07-28 09:40:00

3 Mike TASK3 2009-07-28 09:50:00 2009-07-28 10:30:00

4 Mike task4 2009-07-28 10:20:00 2009-07-28 10:30:00

5 Mike task5 2009-07-28 10:40:00 2009-07-28 11:50:00

Comment puis-je utiliser LINQ to Sql pour la durée du cout temps d'inactivité d'un jour, comme 2009 -07-28?

Le résultat devrait être:

5 minutes (entre Task1, task2 et TASK3) + 10 minutes (entre TASK4 et task5)

= 15 minutes

+1

-1 Cela ressemble à une question de devoirs, et vous n'avez pas donné la preuve d'une tentative décente à résoudre vous-même. –

Répondre

1

Voici un code qui fera le travail, en utilisant Linq. Je ne sais pas si c'est sous la forme que vous cherchiez, mais la logique fonctionne avec les données que vous nous avez fournies. Vous devriez être capable de le réorganiser dans la bonne forme pour votre application.

MODIFIE

var rows = new[] { 
    new { Id = 1, Name="Mike", TaskName="task1", StartTime=DateTime.Parse("2009-07-28 09:00:00"), EndTime=DateTime.Parse("2009-07-28 09:45:00") }, 
    new { Id = 2, Name="Mike", TaskName="task2", StartTime=DateTime.Parse("2009-07-28 09:30:00"), EndTime=DateTime.Parse("2009-07-28 09:40:00") }, 
    new { Id = 3, Name="Mike", TaskName="task3", StartTime=DateTime.Parse("2009-07-28 09:50:00"), EndTime=DateTime.Parse("2009-07-28 10:30:00") }, 
    new { Id = 4, Name="Mike", TaskName="task4", StartTime=DateTime.Parse("2009-07-28 10:20:00"), EndTime=DateTime.Parse("2009-07-28 10:30:00") }, 
    new { Id = 5, Name="Mike", TaskName="task5", StartTime=DateTime.Parse("2009-07-28 10:40:00"), EndTime=DateTime.Parse("2009-07-28 11:50:00") }, 
     }; 

var ranges = rows.Select(x => new { StartTime = x.StartTime, EndTime = x.EndTime }); 
int rangeCount = 0; 
while (ranges.Count() != rangeCount) 
{ 
    rangeCount = ranges.Count(); 
    ranges = ranges.Select(x => new { 
     StartTime = ranges.Where(y => (y.StartTime <= x.StartTime && y.EndTime >= x.StartTime) || (y.StartTime <= x.EndTime && y.EndTime >= x.EndTime)).Min(y => y.StartTime), 
     EndTime = ranges.Where(y => (y.StartTime <= x.StartTime && y.EndTime >= x.StartTime) || (y.StartTime <= x.EndTime && y.EndTime >= x.EndTime)).Max(y => y.EndTime), 
    }).Distinct().ToList(); // ToList required to avoid recursion issues 
} 

TimeSpan gapTime = ranges.Max(x => x.EndTime) - ranges.Min(x => x.StartTime) - new TimeSpan(ranges.Sum(x => (x.EndTime - x.StartTime).Ticks)); 

System.Diagnostics.Trace.WriteLine(gapTime); 
+0

si les données de la tâche1 est: StartTime = 2009-07-28 09:00:00 EndTime = 2009-07-28 09:50:00 alors le résultat est faux. – Mike108

+0

Je vois le problème. Avec le code ci-dessus, vous auriez besoin de calculer récursivement les plages jusqu'à ce que les plages ne puissent pas être réduites. J'espère que j'aurai une meilleure version après que je pourrai retravailler dans quelques heures. –

+0

Ma dernière modification a ajouté une boucle, qui fusionne récursivement les plages jusqu'à ce que seuls les éléments appropriés soient conservés. Cela devrait gérer toutes les données que vous lui lancez. –

-1

Quelque chose comme ça

Supposons que vous ayez une collection d'objets de tâche:

public class Task 
{ 
    public Guid ID { get; set; } 
    public string User { get; set; } 
    public string Task { get; set; } 
    public DateTime TaskStartTime { get; set; } 
    public DateTime TaskFinishTime { get; set; } 
} 

var tasks = new List<Task>(); 
// Fill tasks here... 

var idleTimeInMinutes = 
    tasks.Last().TaskFinishTime.Subtract (tasks.First().TaskStartTime).Minutes 
    - tasks.Sum (t => t.TaskFinishTime.Subtract (t.TaskStartTime).Minutes); 

EDIT: Maintenant, attendez, je vois des tâches se chevaucher dans votre exemple. Alors ce que j'ai écrit ne va pas marcher. Je vais devoir y penser ...

0

Très bien, j'ai mis au point une option qui fonctionnera.

vous pouvez utiliser ceci:

from a in Tasks 
join b in Tasks on true equals true 
where a.TaskStartTime < b.TaskFinishTime 
where a.TaskFinishTime > b.TaskStartTime 
where a.Id < b.Id 
select new { 
    Id = a.Id, 
    User = a.User, 
    Task = (a.Task + " + " + b.Task), 
    TaskStartTime = (a.TaskStartTime < b.TaskStartTime ? a.TaskStartTime : b.TaskStartTime), 
    TaskFinishTime = (a.TaskFinishTime > b.TaskFinishTime ? a.TaskFinishTime : b.TaskFinishTime) 
} 

Pour réduire les tâches incombant aux individuels, jusqu'à ce qu'il n'y ait pas d'intersections, puis prendre la somme de tous les temps, moins la somme du temps dans toutes les tâches.

+0

Merci. J'attends tes bonnes nouvelles. – Mike108

+0

si la tâche1 est: start = 2009-07-28 09:00:00 end = 2009-07-28 09:51:00 le résultat a quelque chose de mal. – Mike108

+0

cela devrait transformer task1 et task2 en quelque chose comme: 'task1 + task2', '2009-07-28 09:00:00', '2009-07-28 09:45:00'. C'est ce que je fais quand je l'essaie avec LINQPad. –

0

Tirez les enregistrements intéressants en mémoire et traitez-les là (en regroupant les plages de chevauchement en plages simples). La tâche d'effondrement ne convient pas à l'interrogation d'approches, telles que sql ou linqtosql.

Questions connexes