我有2个表,一个是帖子另一个是评论。这些表包含" RatedPoint"字段。
我想带5位具有最高分的用户。
例如,用户ID = 1及其在Post表中的总点数
并且它在评论表中的总分为25,因此其总分为75
所以,我必须看完整个成员,然后选择5个最高点
看起来有点复杂,我希望它清楚......
我尝试了类似的东西
var abc= csEntity.Users.Where(u => csEntity.Posts.Any(p => u.Id == p.UserId)).
Take(userCount).OrderByDescending(u => u.Posts.Count).ToList();
或..
var xyz = csEntity.Posts.Where(p => csEntity.Comments.Any(c => c.UserId == p.UserId));
如果可能,我不想使用2个不同的列表..是否可以在一个查询中执行此操作?
我可以用2 for循环来做,但我认为这是一个坏主意..
Post TABLE
评论表
如您所见,这两个表包含userID,每个用户都有RatedPoint ...
我认为现在很清楚
编辑:也许用户永远不会写评论或永远不会写帖子只是写评论..然后我认为我们捣蛋等于posts.userId = comments.UserId
答案 0 :(得分:0)
这是一个LINQ表达式,可以满足您的要求:
var result = from p in posts
join c in comments on p.Id equals c.Id
select new { Id = p.Id, Total = p.Points + c.Points };
提供实际的连接数据。然后你可以像这样选择前5名:
result.OrderByDescending(item => item.Total).Take(5)
请注意,上述情况确实假设两个表始终拥有每个用户,即使他们没有发布或评论。即它们的点数为0.您的更新问题澄清了在您的情况下,您可能存在可能不相交的表,即用户可以在一个表中但不能在另一个表中。
在这种情况下,以下内容适合您:
var leftOuter = from p in posts
join c in comments on p.Id equals c.Id into groupJoin
let c = groupJoin.SingleOrDefault()
select new { Id = p.Id, Total = p.Points + (c == null ? 0 : c.Points) };
var rightAnti = from c in comments
join p in posts on c.Id equals p.Id into groupJoin
let p = groupJoin.SingleOrDefault()
where p == null
select new { Id = c.Id, Total = c.Points };
var result = leftOuter.Concat(rightAnti);
第一个LINQ表达式执行左外连接。第二个LINQ表达式执行左反连接(但我将其称为"右"因为它实际上是原始数据的右连接:))。我使用SingleToDefault()
确保每个用户最多只能在每个表中一次。如果事件证明它们存在多次(否则会导致该用户在最终结果中多次出现),代码将抛出异常。
我承认,我不知道上述是否是最有效的方法。我认为它应该非常接近,因为连接应该被优化(在对象或SQL中),并且这是整个操作中最昂贵的部分。但我对表现没有任何承诺。 :)