2010-01-20 36 views
5

我是新来的LINQ to SQL,我想知道如何实现在LINQ是这样的: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) 
}); 

在此先感谢。

+0

向我们展示您的数据库架构将有所帮助。 – Blindy 2010-01-20 21:51:32

+0

什么是“Criteria.Period”和“Criteria.Period.Value.Month”? – 2010-01-20 21:52:45

+0

是什么让你感到不确定是对的?它是否编译?你有没有试过运行它?它是否提供您期望的结果? – 2010-01-20 21:58:36

回答

6

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

不过,我认为你正在尝试阅读所有可用月份的雇用和终止(然后你可以很容易地过滤它)。如果第一个表(终止)没有包含某个指定月份的任何记录(如May),那么您的查询可能会出错。那么select子句将不会以“May”作为参数调用,即使您在第二个表中有一些数据(表示Hires),那么您也无法找到它。

这可以使用Concat method(请参阅MSDN示例)来优雅地解决。您可以通过选择每月所有termniations和所有员工(成某种类型的数据结构),然后组中的所有数据:

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的懒惰评估,这应该作为单个查询来执行。

+0

这确实是一个很好的答案。我不知道concat方法。我将在稍后尝试并发布我的结果。谢谢。 – jasonco 2010-01-20 22:28:05

+0

你救了我的命。工作很棒!正是我在找的东西。谢谢! +1 – jasonco 2010-01-21 18:18:44

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

感谢您的回答。只要在同一个月内有任何终止或雇用,此版本就可以工作。如果他们中没有任何一个雇佣或者终止,那么即使在5月份雇佣了2名雇员,但是终止雇佣关系,也没有结果出现在特定月份。我不得不做出一个小小的更正,这个群组(由于我的具体情况)应该是 “group t by new {t.TerminationDate.Month,t.TerminationDate.Year} into g”和“group p by new {p。 HireDate.Month,p.HireDate.Year}成g“。除此之外,我认为这是一个很好的答案。谢谢! +1 :-) – jasonco 2010-01-21 18:16:56