1

我有一个用户数据表和另一个 user_ratings 表。这是一对多的关系,因此它们由 连接UserId,users 表是主键,user_ratings 具有外键关系。每个 user_ratings 都有一个名为 rating_value 的列,其中填充了一个整数,负数或正数,并且它被加在一起计算为用户的评级。我希望能够根据给定评级的日期为每个用户提取评级。这是我到目前为止的 linq 声明,但我认为它不正确。

var profiles = from userprofs in Ent.UserProfiles
               join userratings in Ent.UserRatings on userprofs.UserId equals userratings.UserId
               where userratings.DateAdded >= drm.Start
               group userprofs by userprofs.UserId into g
               select new { ... };

不太确定从这里去哪里,我不确定我是否正确使用了该组。我希望稍后能够遍历此集合,以便能够根据 user_ratings 的总和显示每个用户及其相关评分

4

2 回答 2

3

如果您希望了解的有关评级的所有信息都是汇总信息(总和、平均值、计数等),那么您可以执行以下操作:

var profiles = from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  group userrating by userprof into g
  select new {g.Key.UserID, g.Key.UserName, Count = g.Count(), Avg = g.Avg(r => r.RatingValue) };

请注意,我将复数名称更改为单数名称,因为我们根据每个单独的项目定义 linq 查询(UserProfiles 是复数,而 userprof 每个项目都“在”其中)。

这可以很好地直接转换为 SQL:

SELECT up.userID, up.userName, COUNT(ur.*), AVG(ur.ratingValue)
FROM UserProfiles up JOIN UserRatings ur
ON up.userID = ur.userID
WHERE dateAdded > {whatever drm.Start is}
GROUP BY up.userID, up.userName

如果我们希望能够获得单独的评级,这与单个 SQL 查询不太匹配,我们可以这样做:

var profiles = from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  group new{userrating.RatingValue, userrating.SomeThing} by new{userprof.UserID, userprof.UserName};

这将为我们提供一个IEnumerable<Grouping<{anonymous object}, {anonymous object}>>我们可以迭代的对象,在每次迭代中获得一个新的Key.UserIDand Key.UserName,并能够依次迭代得到item.RatingValueand item.SomeThing(我添加用于演示,如果我们只想要它的值IEnumerable<Grouping<{anonymous object}, int>>)就像这个:

foreach(var group in profiles)
{
  Console.WriteLine("The user is :" + group.Key.UserName + " (id: " + group.Key.UserID ")");
  foreach(var item in group)
  {
    Console.WriteLine(item.SomeThing + " was rated " + item.RatingValue);
  }
}

然而,这个问题是没有一个很好的单个 SQL 查询可以映射到。Linq 会尽力而为,但这意味着要执行几个查询,所以你最好帮助它:

var profiles = from item in (from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  select new{userrating.RatingValue, userrating.SomeThing, userprof.UserID, userprof.UserName}).AsEnumerable()
  group new{item.RatingValue, item.SomeThing} by new{item.UserID, item.UserName}

这与以前的输出相同,但转换为 SQL 允许进行单个查询,其余工作在内存中完成。99% 的情况下,像这样将一些工作拖到内存中会降低效率,但是因为之前没有可以映射到的单个 SQL 查询,所以这是一个例外。

于 2012-08-26T21:26:03.997 回答
0

如果我理解你的问题:

from userprofs in Ent.UserProfiles
join userratings in Ent.UserRatings on userprofs.UserId equals userratings.UserId
where userratings.DateAdded >= drm.Start
group new{userprofs,userratings} by userprofs.UserId into g
select new { userId=g.Key, userRating=g.Sum(i=>i.userratings.rating_value) };

GroupBy返回一个IEnumerableIGroupingAnIGrouping基本上是IEnumerable具有额外Key属性的 an,其中包含用于进行分组的属性。如果您Sumrating_value该组的成员,那么您就在那里。

于 2012-08-26T20:18:18.310 回答