2010-01-20 7 views
5

Je suis nouveau à LINQ to SQL et je voudrais savoir comment obtenir quelque chose comme ça dans LINQ:groupe LINQ par mois question

 Month Hires Terminations 
     Jan  5  7 
     Feb  8  8 
     Marc  8  5 

J'ai ce jusqu'à présent, et je pense qu'il est quelque chose qui ne va pas avec mais je ne suis pas sûr:

from term1 in HRSystemDB.Terminations 
group term1 by new { term1.TerminationDate.Month, term1.TerminationDate.Year } into grpTerm 
select new HiresVsTerminationsQuery 
{ 
    Date = Criteria.Period, 
    TerminationsCount = grpTerm.Count(term => term.TerminationDate.Month == Criteria.Period.Value.Month), 
    HiresCount = (from emp in HRSystemDB.Persons.OfType<Employee>() 
       group emp by new { emp.HireDate.Month, emp.HireDate.Year } into grpEmp 
       select grpEmp).Count(e => e.Key.Month == Criteria.Period.Value.Month) 
}); 

Merci d'avance.

+0

Nous montrer votre schéma de base de données aiderait. – Blindy

+0

Qu'est-ce que 'Criteria.Period' et' Criteria.Period.Value.Month'? –

+0

Qu'est-ce qui vous fait douter que c'est juste? Est-ce qu'il compile? Avez-vous essayé de l'exécuter? Cela donne-t-il les résultats que vous attendez? –

Répondre

6

Je ne sais pas d'où vient la valeur Criteria.Period dans votre exemple de requête.

Cependant, je pense que vous essayez de lire les embauches et les terminaisons pour tous les mois disponibles (et vous pouvez facilement le filtrer). Votre requête pourrait mal tourner si la première table (Résiliation) n'incluait aucun enregistrement pour un mois spécifié (disons en mai). Alors la clause select ne serait pas appelée avec "May" comme paramètre et même si vous aviez quelques données dans la deuxième table (représentant Hires), alors vous ne pourriez pas le trouver.

Cela peut être élégamment résolu en utilisant le Concat method (voir les exemples MSDN). Vous pouvez sélectionner tous termniations et tous les employés (dans une structure de données d'un certain type) et puis regrouper toutes les données par mois:

var terms = from t in HRSystemDB.Terminations 
      select new { Month = t.TerminationDate.Month, 
         Year = term1.TerminationDate.Year, 
         IsHire = false }; 
var hires = from emp in HRSystemDB.Persons.OfType<Employee>() 
      select new { Month = emp.HireDate.Month, 
         Year = emp.HireDate.Year 
         IsHire = true }; 

// Now we can merge the two inputs into one 
var summary = terms.Concat(hires); 

// And group the data using month or year 
var res = from s in summary 
      group s by new { s.Year, s.Month } into g 
      select new { Period = g.Key, 
         Hires = g.Count(info => info.IsHire), 
         Terminations = g.Count(info => !info.IsHire) } 

Lorsque l'on regarde le code maintenant, je suis sûr qu'il ya une certaine façon plus courte écrire ceci. D'un autre côté, ce code devrait être très lisible, ce qui est un avantage. Notez également que cela n'a pas d'importance que nous divisons le code en quelques sous-requêtes. Merci à evalutation paresseux de LINQ à SQL, cela devrait être exécuté comme une seule requête.

+0

C'est une très bonne réponse en effet. Je ne connaissais pas la méthode concat. Je vais l'expérimenter plus tard et afficher mes résultats. Merci. – jasonco

+0

Vous m'avez sauvé la vie. J'ai bien travaillé! Exactement ce que je cherchais. Merci! +1 – jasonco

3

Je ne sais pas s'il est plus court mais vous pouvez également essayer cette version pour voir si cela fonctionne mieux avec votre serveur. Je ne sais pas exactement comment ces deux réponses se transforment en déclarations SQL. On pourrait être mieux basé sur vos index et autres.

var terms = 
    from t in Terminations 
    group t by new {t.Month, t.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var hires = 
    from p in Persons 
    group p by new {p.Month, p.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var summary = 
    from t in terms 
    join h in hires on t.Key equals h.Key 
    select new {t.Key.Month, t.Key.Year, 
     Hires = h.Count, Terms = t.Count}; 
+0

Merci pour la réponse. Cette version fonctionne aussi longtemps qu'il y avait des résiliations ou des embauches dans le même mois. S'il n'y a pas d'embauches ou de résiliations dans l'un ou l'autre des cas, aucun résultat n'apparaîtra pour ce mois particulier, même s'il y a eu, par exemple, 2 embauches mais aucune résiliation en mai. Je devais faire une petite correction, le groupe par (pour mon cas particulier) devrait être "groupe t par new {t.TerminationDate.Month, t.TerminationDate.Year} en g" et "groupe p par new {p. HireDate.Month, p.HireDate.Year} en g ". À part ça, je pense que c'est une bonne réponse. Merci! +1 :-) – jasonco