Linq to SQL,选择列为max的不同行?

时间:2011-10-11 17:20:49

标签: .net linq linq-to-sql distinct max

编辑:简化问题和澄清问题。

我正在尝试将此存储过程转换为LINQ语句:

SELECT UserID, MAX(RowID) as RowID into #tempa
FROM Users
WHERE Approved = 1 
GROUP BY UserID

SELECT (bunch of columns)
FROM Users INNER JOIN #tempa
ON (Users.UserID = #tempa.UserID AND Users.RowID = #tempa.RowID)
DROP TABLE #tempa

当我运行这个SPROC时,我得到了292行。当我尝试将其转换为LINQ时,我会执行以下操作:

IQueryable<User> userQuery = db.Users.Where(x => x.Approved == true);
        userQuery = userQuery.Where((x => x.RowID ==
                        db.Users.Where(u => u.UserID == x.UserID).Max(u => u.RowID)
           ));
         IList<User> users = userQuery.ToList();

结果是293行......

现在我将SPROC更改为(它是一个位值,其中值2处于活动状态):

SELECT UserID, MAX(RowID) as RowID into #tempa
FROM Users
WHERE Approved = 1 AND (UserAttribtues & 2) = 2
GROUP BY UserID

SELECT (bunch of columns)
FROM Users INNER JOIN #tempa
ON (Users.UserID = #tempa.UserID AND Users.RowID = #tempa.RowID)
DROP TABLE #tempa

我用sproc获得了289行。

使用LINQ尝试以下内容:

 IQueryable<User> userQuery = db.Users.Where(x => (x.UserAttributes & Convert.ToInt32(UserAttributes.Active)) == Convert.ToInt32(UserAttributes.Active) && x.Approved == true);
        userQuery = userQuery.Where((x => x.RowID ==
                        db.Users.Where(u => u.UserID == x.UserID).Max(u => u.RowID)
           ));

结果是127行....

起初我以为这是我在子查询中使用.Max,AD.NET在下面对我进行了修正,但数字仍然没有了,我在这里缺少什么?我不明白......

2 个答案:

答案 0 :(得分:2)

这样的东西应该可行,你也可以从中重构一些谓词。

 predicate = predicate.And((x => x.RowId == 
                                        db.Users
                                             .Where(u=>u.UserId ==x.UserId)
                                             .Max(u=>u.RowId)
                           ));

您可以尝试这样的事情:

var result = from u in db.Users
let max = db.Users.Where(au=>au.UserId == u.UserId).Max(au=>au.RowId)
let maxUId = db.Users.Where(au=>au.UserId == u.UserId && au.RowId == max).Select(au=>au.UserId).FirstOrDefault()
where u.RowId == max && u.UserId == maxUId
select u

检查对sql(删除任何其他条件请调试)。 我想我错过了userId部分,你也需要匹配userId,否则它应该不能正常工作。我相信您可以使查询更好一些,例如,使用let来保留具有最高rowid的整个用户对象,然后您可以使用该对象来匹配rowid和userid。

答案 1 :(得分:1)

// Filter the list
var q = from s in userQuery 
    group s by s.UserId into g
     select new {UserId = g.Key, MaxRowId = g.Group.Max(s => s.RowId) } 

// Apply the filter
userQuery = userQuery.Where(i => q.Where(k => k.UserId == i.UserId && k.MaxRowId == i.RowId).Count() > 0).ToList();