2011-11-03 111 views
1

C#和VB.NET中的示例都可以。LINQ to SQL按年龄分组的人

我有一个表 “人” 与下列:

-FullName(nvarchar的不是null) -DOB(日期时间为空)

我想写一个LINQ to SQL来组人的年龄,像下面的结果:

年龄19:4 PPL

年龄20:5 PPL

年龄21:6个PPL

等等...

这里是我的尝试:

Dim query = From ppl In db.People _ 
     Select New With {.Age = DateTime.Now.Year - CDate(ppl.DOB).Year, .CountAge = ppl.Count} 

注意,有一些人在表中没有DOB记录,所以这些不得被包括在内。 DOB列有这样的记录1982-10-24 10:12:45 AM因为它是一个DateTime列。

+0

“请注意,有一些人在表格中记录DOB ......”你缺少一个字句子? –

+0

它应该是“有些人没有DOB记录”。是的,我没有输入“不”字。谢谢。 – Narazana

+0

对于初学者来说有几个问题:'.Age = DateTime.Now.Year - CDate(ppl.DOB).Year'将会在很多时候得到错误的年龄(考虑一年中出生日期的位置)。你也没有聚合在那里。 –

回答

0

我宁愿:

var result = db.People 
    .Where(p => p.DOB != null) // exclude null DOB's from stats 
    .GroupBy(p => p.DOB.Value.Year) 
    .Select(g => new { Age = DateTime.Now.Year - g.Key, Count = g.Count() }); 

我们在这里分组对抗的出生年份。这应该转化为SQL中的GROUP BY YEAR(dob),与GROUP BY YEAR(GETDATE()) - YEAR(dob)相比,该性能或优化可能会稍微好一些。将行表达式映射到索引几乎是不可能的,但像YEAR()这样的特定结构可以被优化为部分使用日期时间索引。我在这里做了许多假设,就像datetime结构以年份开始,SQL服务器关心YEAR(x)以进行优化等。在构建LINQ查询时,记住这种情况仍然很好。

0
From ppl In db.People 
Select New With {.Age = DateTime.Now.Year - CDate(ppl.DOB).Year, 
       .CountAge = ppl.Count()} 
Group By (DateTime.Now.Year - CDate(ppl.DOB).Year) 

我认为这个查询将用于您的目的。

0

假设DOB是一个可空的日期时间(日期时间?),所以没有DOB记录意味着零有:

from ppl in db.People 
    where ppl.DOB.HasValue 
    let age = DateTime.Today.Year - ppl.DOB.Value.Year 
    group ppl by age into ages 
    select new { Age=ages.Key, Persons = ages } 

这是在C#中,但应该很好的转化为VB因为语法是相似的。

+0

如果两个人在一月和十二月出生,他们的年龄与您的查询不同吗? –

+0

的确,这只是一个不好的近似,但遵循OP所使用的逻辑。他的问题是关于分组,所以我想保持它像他的:) – edvaldig

0

这应该工作(也应该多一点准确地计算年龄):

var query = from person in db.People 
      where person.DOB.HasValue 
      let age = (DateTime.Now - username.UpdateDateTime.Value).Days % 365 
      group person by age into ages 
      select new { Age =ages.Key, People = ages.Count() } 
2

更准确的解决方案:

db.People.Where(p => p.DOB != null).GroupBy(p => ((DbFunctions.DiffDays(p.DOB, DateTime.Today)/365))) 
.Select(g => new {Age=g.Key, Count = g.Count()}) 

分组为区间:

var interval = 5; //years 
db.People.Where(p => p.DOB != null).GroupBy(p => ((DbFunctions.DiffDays(p.DOB, DateTime.Today)/365)/interval)) 
.Select(g => new {GroupIndex=g.Key, Count = g.Count()})