如何编写LINQ查询获取用户及其首篇文章?
解决方案
思路1:先分组取首篇文章时间,再关联查询
这种方式贴合你原始SQL的逻辑,先通过分组获取每个用户最早的文章创建时间,再关联用户表和文章表筛选对应数据,避免将所有用户字段加入GROUP BY:
// 先获取每个用户的首篇文章创建时间 var userFirstArticleDates = db.Articles .GroupBy(a => a.UserId) .Select(g => new { UserId = g.Key, FirstCreatedAt = g.Min(a => a.CreatedAt) }); // 关联用户、首篇时间和文章表,得到最终结果 var result = from u in db.Users join ufad in userFirstArticleDates on u.Id equals ufad.UserId join a in db.Articles on new { u.Id, ufad.FirstCreatedAt } equals new { a.UserId, a.CreatedAt } orderby u.Id, a.CreatedAt, a.Id select new { UserId = u.Id, Username = u.Username, ArticleId = a.Id, FirstArticleCreatedAt = a.CreatedAt };
思路2:使用窗口函数筛选首篇文章
如果你的ORM支持窗口函数(比如EF Core 3.0及以上版本),可以用RowNumber()按用户分组、按创建时间排序,直接提取每个用户的第一篇文章,代码更简洁:
var result = db.Articles .Select(a => new { UserId = a.User.Id, Username = a.User.Username, ArticleId = a.Id, CreatedAt = a.CreatedAt, // 按用户分组,按创建时间、文章ID升序排,标记行号 RowNum = EF.Functions.RowNumber().Over( partitionBy: a.UserId, orderBy: a.CreatedAt ascending, a.Id ascending) }) .Where(x => x.RowNum == 1) // 只取每组的第一行(首篇文章) .OrderBy(x => x.UserId) .Select(x => new { x.UserId, x.Username, x.ArticleId, FirstArticle = x.CreatedAt });
关于你之前代码的问题
你之前用new { user }作为分组键,LINQ会把整个User对象的所有字段都纳入分组条件,所以生成的SQL会包含所有用户字段的GROUP BY。要仅按Id分组,必须先通过分组拿到首篇文章的关键信息,再关联回用户表获取其他字段,而不是直接在分组中引用整个User对象。
内容的提问来源于stack exchange,提问作者glen-84
相关产品推荐
相关产品推荐

