LINQ to SQL按年龄分组人

时间:2011-11-03 08:30:03

标签: c# vb.net linq linq-to-sql

  

C#和VB.NET中的示例都可以。

我有一个表“People”,其中包含以下列:

-FullName(nvarchar not null) -DOB(datetime null)

我想写一个LINQ to SQL来按年龄对人进行分组,如下面的结果:

年龄19:4 ppl

年龄20:5人

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列。

6 个答案:

答案 0 :(得分: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()})

答案 1 :(得分:1)

如果您使用的是EF Core 3.1,则DbFunctions已替换为EF.Functions。 作为另一种选择,您可以使用以下方法:

var query = await db.People
                 .GroupBy(x.DateOfBirth.HasValue ? (int)(EF.Functions.DateDiffDay(x.DateOfBirth.Value, DateTime.UtcNow) / 365.25) : (int?)null)
                  .Select(x => new
                  {
                      Age = x.Key,
                      Count = x.Count(),
                  })
                .ToListAsync(cancellationToken);

它考虑了“生日”,而不是时间,但比仅使用“生日”更准确

答案 2 :(得分: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)

我认为此查询符合您的目的。

答案 3 :(得分:0)

假设DOB是可以为空的DateTime(DateTime?),那么在那里没有DOB记录意味着null:

  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。

答案 4 :(得分: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() }

答案 5 :(得分: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查询时要记住这种情况仍然很好。