7
votes

Sélectionnez uniquement le premier enregistrement dans un intervalle de temps

J'ai suivi du tableau

db.DeviceLogs.GroupBy(g=>new {g.LogDate.Year, 
                              g.LogDate.Month, 
                              g.LogDate.Day, 
                              g.LogDate.Hour, 
                              g.LogDate.Minutes, 
                              g.UserID})
             .Select(s=>new {UserID=s.Key.UserID, s.???});


7 commentaires

Je ne pense pas que vous puissiez le faire dans Linq-to-SQL. Vous pouvez le faire sous Linq-to-Objects en abusant Groupby avec une comparaison personnalisée ou avec une méthode de type Linq personnalisée (bien que cela n'utilise plus Linq).


J'ai besoin d'un peu de clarification. Toutes les entrées après cinq minutes seront-elles incluses ou, l'échantillonnage continue-t-il? S'il se poursuit, les fenêtres de cinq minutes restent-elles basées sur la première entrée ou, chaque fenêtre commence-t-elle à partir du dernier accepté?


@JODRELL: Oui, seule la fenêtre est de 5 minutes, les entrées sont des mois et du long de l'année. Deuxièmement, cinq minutes de fenêtre restent basées sur la première entrée de l'ensemble de données de cet utilisateur spécifique.


@Marshal, restauration, peut répondre à un groupe dans des fenêtres de cinq minutes à basculer sur le premier événement.


Votre ligne uniquement des enregistrements qui ont eu lieu après 5 minutes de l'enregistrement précédent sélectionné semble être en attente avec Fenêtre de cinq minutes restent basés sur la première entrée .


@Rawling: édité cette partie de clarification. Je savais qu'il serait difficile d'expliquer afin que j'ai également inclus la sortie souhaitée


Nous avons vraiment besoin de plus de données pour obtenir ce que vous voulez dire. Par exemple, si vous avez un enregistrement à 0:00, un enregistrement à 0:07, et un enregistrement à 0:11 (tous pour le même identifiant), avez-vous (a) définir vos fenêtres comme 0-5, 5- 10 et 10-15 et renvoyez ainsi tous les trois enregistrements car ils se trouvent tous dans des fenêtres séparées ou vous (b) renvoyez-vous 0:00, 0:07 (car 7-0> 5) mais pas 0:11 (parce que 11- 7 <5)?


5 Réponses :


5
votes
var result =
    from log in db.DeviceLogs
    let byId = 
        db.DeviceLogs.Where(item => item.UserId == log.UserId)
    let first =
        byId.First(item => item.LogDate == byId.Min(min => min.LogDate))
    where 
        log.Equals(first) || (log.LogDate - first.LogDate).Minutes > 5
    select log;

8 commentaires

1 sec, pls. Semble que l'erreur est que vous comparez avec un minimumDate Element entre tous les enregistrements, pendant que vous devez comparer au minimum spécifique à l'utilisateur. Pls, vois ma réponse.


.where (item => item.userid == log.userid) contraintes Le jeu recherché sur l'utilisateur :)


C'est une version modifiée de votre réponse avec une sortie à Linqpad, bien que je ne nie pas votre réponse était une base. Et je t'ai donné un uppote


db.devicelogs.min (min => min.logdate) n'est pas contraint, c'est juste la date minimale


Vous faites à peine la même chose que moi et simplement mettre la chose de filtrage d'identifiant dans une variable supplémentaire ... votre réponse fait l'original la même chose que la mienne.


D'accord, puis changez votre réponse et je vais supprimer le mien.


@Janp. Merci de réponse .. Je vais essayer de revenir.


@Janp. Il fonctionne bien avec db.devicelogs mais il échoue si je travaille avec Liste



2
votes

OK, que diriez-vous.

var firstDates = db.DeviceLogs.GroupBy(d => d.UserId).ToDictionary(
    g => g.Key,
    g => g.OrderBy(d => d.LogDate).First().LogDate);

db.DeviceLogs.GroupBy(g => new
  {
    v = Math.Floor(SqlMethods.DateDiffMinute(firstDates[d.UserId], g.LogDate) / 5),
    u = g.UserID
  }).Select(s => s.OrderBy(s => s.LogDate).First());


3 commentaires

J'ai supprimé mon DV car ce n'est pas aussi faux comme je me suis trompé que je pensais à première vue, mais cela ne fera que observer le premier élément par utilisateur par une minute absolue plutôt qu'un premier article-per-utilisateur-perfublier-cinq -Minute-fenêtre.


@Rawling, modifié après des éclaircissements.


Cela donne une erreur dans l'énoncé de groupeBy: Déclarateur de membre anonyme non valide. Les membres de type anonyme doivent être déclarés avec une affectation de membre, un nom simple ou un accès membre.



1
votes

Je peux vous suggérer une solution SQL: xxx

voir fiddler http://sqlfiddle.com/#!6/fa74e/50


1 commentaires

Merci voo .. mais il est très difficile pour moi de le convertir en Linq: p



1
votes

Je ne suis pas sûr de pouvoir le faire avec une seule instruction LINQ, car vous devez vous rappeler que la date d'heure du dernier enregistrement cédée. Vous pouvez utiliser un bloc d'itérateur comme: xxx

où l'enregistrement serait une classe pour représenter un seul enregistrement, qui comprend une propriété DateTime de type DateTime (voir ici ). Si votre propriété logDate est d'un type différent, vous devrez peut-être modifier le code un peu.


0 commentaires

1
votes

Ceci est ma solution xxx


0 commentaires