LINQ group by month问题

时间:2010-01-20 21:41:23

标签: c# .net linq

我是LINQ to SQL的新手,我想知道如何在LINQ中实现这样的东西:

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

到目前为止我已经得到了这个,我认为它有问题,但我不确定:

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)
});

提前致谢。

2 个答案:

答案 0 :(得分:6)

我不太确定示例查询中Criteria.Period值的来源。

但是,我认为您正在尝试阅读所有可用月份的招聘和终止(然后您可以轻松过滤它)。如果第一个表(终止)没有包含某个指定月份的任何记录(比如五月),那么您的查询可能会出错。然后,select子句将不会被调用“May”作为参数,即使您在第二个表中有一些数据(代表Hires),那么您将无法找到它。 / p>

使用Concat method可以很好地解决这个问题(参见MSDN示例)。您可以选择所有的术语和所有雇员(进入某种类型的数据结构),然后按月对所有数据进行分组:

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) }

现在查看代码时,我很确定有一些更短的方法来编写它。另一方面,这段代码应该是非常易读的,这是一个好处。另请注意,我们将代码拆分为几个子查询并不重要。由于LINQ to SQL的惰性评估,这应该作为单个查询执行。

答案 1 :(得分:3)

我不知道它是否更短但您也可以尝试使用此版本来查看它是否适用于您的服务器。我不确切地知道这两个答案如何变成SQL语句。根据您的索引等可能会更好。

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};