Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ到SQL按年龄分组_C#_Vb.net_Linq_Linq To Sql - Fatal编程技术网

C# LINQ到SQL按年龄分组

C# LINQ到SQL按年龄分组,c#,vb.net,linq,linq-to-sql,C#,Vb.net,Linq,Linq To Sql,C#和VB.NET中的示例都可以 我有一个“People”表,其中包含以下列: -全名(nvarchar非空) -DOB(日期时间为空) 我想编写一个LINQ to SQL来按年龄对这些人进行分组,结果如下: 年龄19:4 ppl 20岁:5人 21岁:6人 等等 以下是我的尝试: Dim query = From ppl In db.People _ Select New With {.Age = DateTime.Now.Year - CDate(ppl.DOB).Year

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

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

-全名(nvarchar非空) -DOB(日期时间为空)

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

年龄19:4 ppl

20岁:5人

21岁:6人

等等

以下是我的尝试:

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-2410:12:45AM,因为它是一个日期时间列

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)

我认为这个查询可以满足您的需要。

假设DOB是一个可空的DateTime(DateTime?),那么没有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

这应该有效(并且应该更准确地计算年龄):

我宁愿:

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中的
groupbyyear(dob)
,与
groupbyyear(GETDATE())-YEAR(dob)
相比,它的性能或优化性能稍好一些。几乎不可能将行表达式映射到索引中,但某些构造(如
YEAR()
)可以单独进行优化,以部分使用日期时间索引。不过,我在这里做了很多假设,比如
datetime
结构以年开始,SQL server关心
year(x)
进行优化等。在构造LINQ查询时,最好记住这种情况。

更准确的解决方案:

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

如果您使用的是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);

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

“注意,表格中有些人有DOB记录……”这句话中是否遗漏了一个词?应该是“有些人没有DOB记录”。是的,我没有打“否”这个词。Thx.对于初学者来说,有两个问题:
.Age=DateTime.Now.Year-CDate(ppl.DOB)。Year
在大多数情况下都会得到错误的年龄(考虑一年中出生日期的位置)。此外,这里根本没有聚合。如果两个人出生在1月和12月,他们在你的查询中是否仍然具有相同的年龄?事实上,这只是一个糟糕的近似值,但遵循OP使用的逻辑。他的问题是关于分组的,所以我想保持和他的一样:)
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);