How do I write a LINQ query that would translate to the following SQL?
SELECT u.id, u.username, a.id, MIN(a.created_at) AS firstArticle
FROM users u
INNER JOIN editorial_articles a
ON a.user_id = u.id
GROUP BY u.id
ORDER BY u.id, a.created_at, a.id
Basically, a list of users with their first article.
Everything that I try results in an incorrect group-by clause (too many columns), not enough columns selected, or some other issue.
I've tried a thousand different combinations – why is this so difficult?
Classes:
[Table("users")]
public class User
{
[Column("id", IsPrimaryKey = true, IsIdentity = true, SkipOnInsert = true, SkipOnUpdate = true)]
public int Id { get; set; } // int
[Column("username", CanBeNull = false)]
public string Username { get; set; } = null!; // varchar(20)
[Association(ThisKey = nameof(Id), OtherKey = nameof(Article.UserId))]
public IEnumerable<Article> Articles { get; set; } = null!;
}
[Table("articles")]
public class Article
{
[Column("id", IsPrimaryKey = true, IsIdentity = true, SkipOnInsert = true, SkipOnUpdate = true)]
public int Id { get; set; } // int
[Column("user_id")]
public int UserId { get; set; } // int
[Column("created_at")]
public DateTime CreatedAt { get; set; } // datetime
[Association(CanBeNull = false, ThisKey = nameof(UserId), OtherKey = nameof(User.Id))]
public User User { get; set; } = null!;
}
Update:
The closest that I get with a GROUP BY is:
var result =
from user in db.Users
join article in db.Articles
on user.Id equals article.UserId into articles
from article in articles
group article by new { user } into g
orderby g.Key.user.Id, g.Min(a => a.CreatedAt), g.Min(a => a.Id)
select new
{
User = g.Key,
FirstArticle = g.Min(a => a.CreatedAt)
};
I don't like that it puts all of the user fields into the group-by. If you just group by Id, then it's not possible to reference the initial user in the select.
Is there no way to group by ID, but select additional fields?
Use Window Function
ROW_NUMBERfor such task: