[英]Linq - Grouping by date and selecting count
我目前正在解决一个问题,我想运行一个查询,该查询按所选日期对结果进行分组。
对于这个例子,想象一个简单的 model 像这样:
public class User
{
public DateTime LastLogIn {get; set;}
public string Name {get; set;}
}
我正在寻找的解决方案是获取按日期登录的用户数。 在数据库中,DateTime 与日期和时间组件一起存储,但对于此查询,我实际上只关心日期。
我目前拥有的是:
context.Users
.Where((x.LastLogIn >= lastWeek)
&& (x.LastLogIn <= DateTime.Now))
.GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
.Select(x => new
{
Value = x.Count(),
Day = (DateTime)EntityFunctions.TruncateTime(x.Key)
}).ToList();
然而,上面返回一个空列表。
最终目标是拥有一个对象列表,其中包含一个值(一天登录的用户数)和一天(相关日期)
有什么想法吗?
将查询更改为:
context.Users
.Where((x.LastLogIn >= lastWeek)
&& (x.LastLogIn <= DateTime.Now))
.GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
.Select(x => new
{
Value = x.Count(),
Day = (DateTime)x.Key
}).ToList();
它现在返回一个包含单个项目的列表,其中 Value 是与 where 子句匹配的用户总数,Day 是第一天。 好像还是没能按天分组
注意:事实证明上面的代码是正确的,我只是做错了其他事情。
它生成的 Sql 是(注意这里可能有非常轻微的语法错误,我针对示例对其进行了调整):
SELECT
1 AS [C1],
[GroupBy1].[A1] AS [C2],
CAST( [GroupBy1].[K1] AS datetime2) AS [C3]
FROM ( SELECT
[Filter1].[K1] AS [K1],
COUNT([Filter1].[A1]) AS [A1]
FROM ( SELECT
convert (datetime2, convert(varchar(255), [Extent1].[LastLogIn], 102) , 102) AS [K1],
1 AS [A1]
FROM [dbo].[Users] AS [Extent1]
WHERE (([Extent1].[LastLogIn] >= @p__linq__1) AND ([Extent1].[LastLogIn] <= @p__linq__2)
) AS [Filter1]
GROUP BY [K1]
) AS [GroupBy1]
您不需要那里的第二个TruncateTime
:
context.Users
.Where((x.LastLogIn >= lastWeek) && (x.LastLogIn <= DateTime.Now))
.GroupBy(x => DbFunctions.TruncateTime(x.LastLogIn))
.Select(x => new
{
Value = x.Count(),
// Replace the commented line
//Day = (DateTime)DbFunctions.TruncateTime(x.Key)
// ...with this line
Day = (DateTime)x.Key
}).ToList();
GroupBy
已经从DateTime
截断了时间,因此您不需要再次调用它。
要使用DbFunctions.TruncateTime
您需要引用程序集System.Data.Entity
并包括using System.Data.Entity;
注意:已编辑以解决EntityFunctions
弃用问题。
试试这个:
.GroupBy(x => new {Year = x.LastLogIn.Year, Month = x.LastLogIn.Month, Day = x.LastLogIn.Day)
.Select(x => new
{
Value = x.Count(),
Year = x.Key.Year,
Month = x.Key.Month,
Day = x.Key.Day
})
您可以轻松做到:
yourDateList.GroupBy(i => i.ToString("yyyyMMdd"))
.Select(i => new
{
Date = DateTime.ParseExact(i.Key, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None),
Count = i.Count()
});
我遇到了同样的问题,以通过日期时间列获取基于组的计数。 这就是我所做的。 感谢这里的一些答案。 我尝试了最小版本,并在 .netcore 解决方案中使用了此代码。
var result = _context.yourdbmodel
.GroupBy(x=>x.yourdatetimecolumn.Value.Date)
.select(x=> new
{
Count = x.Count(),
Date = (DateTime)x.Key // or x.Key.Date (excluding time info) or x.Key.Date.ToString() (give only Date in string format)
})
.ToList();
示例输出:
[ { "requestDate": "2020-04-01", "requestCount": 3 }, { "requestDate": "2020-04-07", "requestCount": 14 } ]
希望这对将来的人有所帮助。
您也可以在一行中完成。
var b = (from a in ctx.Candidates select a)
.GroupBy(x => x.CreatedTimestamp.Date).Select(g => new { Date=(g.Key).ToShortDateString(), Count = g.Count() });
我以这种方式仅按日期解决了分组:
var result = _context.yourdbmodel
.GroupBy(x=> DbFunctions.TruncateTime(x.yourdatetimecolumn))
.select(x=> new
{
Count = x.Count(),
Date = (DateTime)x.Key
})
.ToList();
要使用DbFunctions.TruncateTime
您需要引用程序集System.Data.Entity
并包括 using System.Data.Entity
。
只需在 ToList() 的帮助下首先将 IQueryable 转换为 IEnumerable(List) 然后使用 groupby
context.Users
.Where((x.LastLogIn >= lastWeek) && (x.LastLogIn <= DateTime.Now))
.ToList()
.GroupBy(x => x.LastLogIn.Date))
.Select(x => new
{
Value = x.Count(),
Day = (DateTime)x.Key
}).ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.