2 votes

Linq-To-SQL GroupBy: Comment calculer la colonne de pourcentage

J'ai une table de base de données d'événements. Chaque événement a une catégorie et une date/heure.

(en fait, les événements ont des sous-catégories qui sont contenues dans des catégories et diverses autres propriétés, omises dans cet exemple simplifié)

Je veux générer une liste avec une entrée pour chaque heure et catégorie, en indiquant le nombre d'événements et leur pourcentage.

date            | catégorie | nombre d'événements | pourcentage
----------------------------------------------------------
2012-01-01 1:00 | cat-1    | 10               | 50%
2012-01-01 1:00 | cat-2    | 10               | 50%
2012-01-01 2:00 | cat-1    | 1                | 10%
2012-01-01 2:00 | cat-2    | 9                | 90%
2012-01-01 3:00 | cat-1    | 3                | 100%
...

J'ai du mal à calculer le pourcentage de manière efficace. Voici ce que j'ai jusqu'à présent:

var résultats = datacontext.events.
  groupBy(e=>new   
  {  // group by category and hour
     catégorie = e.catégorie,
     datetime = new DateTime (
       e.datetime.Year, e.datetime.Month, e.datetime.Day, 
       e.datetime.Hour, 0, 0 ) 
     // utilisez date+heure pour regrouper, ignorez les minutes/secondes
  }).
  sélectionner(groupe => new 
  {
     catégorie = groupe.Key.catégorie,
     datetime = groupe.Key.datetime,
     nombre d'événements = groupe.count(),
     pourcentage = groupe.count() / ["nombre total d'événements pour cette heure"] * 100.0
  }

Comment puis-je obtenir la valeur pour [nombre total d'événements pour cette heure], idéalement de manière élégante et efficace?

4voto

Joe Points 34413

Voici ce que j'ai trouvé :

        var results = from events in datacontext.events
                      let date = new DateTime(
                             events.datetime.Year, events.datetime.Month, events.datetime.Day,
                             events.datetime.Hour, 0, 0)
                      let total = datacontext.events.Where(x => x.datetime.Date == date.Date && x.datetime.Hour == date.Hour).Count()
                      group events by new
                      {  // group by category and hour
                          category = events.category,
                          datetime = date,
                          total = total
                      } into e
                      select new
                      {
                          category = e.Key.category,
                          day = e.Key.datetime.Day,
                          numberOfEvents = e.Count(),
                          percentage = (float)e.Count() / (float)e.Key.total
                      };

Deux points à noter :

  1. Utilisation de floats pour le pourcentage
  2. utilisation de let pour calculer le total pour la Date

1voto

Vous devrez d'abord regrouper par jour, puis sélectionner les totaux à partir de là... quelque chose comme :

var resultsPerDay = datacontext.events.groupBy(e=>new {
        datetime = new DateTime (
            e.datetime.Year, e.datetime.Month, e.datetime.Day, 
            e.datetime.Hour, 0, 0 )
        }
    }).select(group=>new {
        datetime = group.Key.datetime,
        totalForADay = group.Key.count()
    });

var results = datacontext.events.
  groupBy(e=>new   
  {  // groupe par catégorie et heure
     category = e.category,
     datetime = new DateTime (
       e.datetime.Year, e.datetime.Month, e.datetime.Day, 
       e.datetime.Hour, 0, 0 ) 
     // utilisez la date+heure pour le regroupement, ignorez les minutes/secondes
  }).
  select(group => new 
  {
     category = group.Key.category,
     datetime = group.Key.datetime,
     numberOfEvents = group.count(),
     percentage = 100 * group.count() / resultsPerDay.where(p=>p.datetime == group.Key.datetime).select(p=>p.totalForADay).SingleOrDefault()
  }

Je ne suis pas sûr que ce soit la manière la plus efficace, cependant. De plus, je ne suis pas sûr de la syntaxe car je ne l'ai pas compilée, mais vous avez compris l'idée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X