我试图获得所有餐馆的平均评分,并返回与该ID相关的所有resteraunts的名称,我能够写一个sql语句来获得餐馆的平均值以及餐馆的名称但是我想要的只返回一次餐馆的名称。
Select t.Average, Name from [dbo].[Reviews] as rev
join [dbo].[Resteraunts] as rest
on rest.ResterauntId = rev.ResterauntId
inner join
(
SELECT [ResterauntId],
Avg(Rating) AS Average
FROM [dbo].[Reviews]
GROUP BY [ResterauntId]
)
as t on t.ResterauntId = rest.ResterauntId
resteraunt class
public int ResterauntId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public virtual ICollection<Review> Reviews { get; set; }
public virtual Review reviews{ get; set; }
复习课程
public int ReviewId { get; set; }
public double Rating { get; set; }
[ForeignKey("ResterauntId")]
Resteraunt Resteraunt { get; set; }
public int ResterauntId { get; set; }
public DateTime DateOfReview { get; set; }
如果可能的话,我希望将答案转换为linq。
答案 0 :(得分:3)
Resteurants.Select(r => new {
Average = r.Reviews.Average(rev => rev.Rating),
r.Name
})
这应该会为您提供一组对象Average
(该餐厅的所有评论的平均值)和餐馆的Name
。
这假设您已正确设置关系,以便Restaurant.Reviews
仅引用按ID匹配的关系。
如果你没有设置这种关系,你需要自己过滤它:
Resteurants.Select(r => new {
Average = Reviews.Where(rev => rev.ResteurantId == r.Id).Average(rev => rev.Rating),
r.Name
})
答案 1 :(得分:2)
首先,你的模型似乎有比所需更多的聚合,我冒昧地修剪它并移除额外的字段,理想情况下你需要两个模型RestaurantId
之间的关系,{{1的主键和Restaurant
的外键(1:N)
Review
如果这些是模型,那么您只需要public class Restaurant
{
public int RestaurantId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public virtual ICollection<Review> Reviews { get; set; }
}
public class Review
{
public int ReviewId { get; set; }
public double Rating { get; set; }
public int RestaurantId { get; set; }
public DateTime DateOfReview { get; set; }
}
,因为内部包含审核集合,那么您需要的只是:
List<Restaurant> restaurantList
如果没有集合聚合,并且您有单独的ReviewList,如下所示:var result =
restaurantList.Select(x => new {
Name = x.Name,
Average = x.Reviews.Average(y => y.Rating)
}
);
,请执行以下操作:
List<Review> reviewList
另请注意,由于我们使用的是var result =
reviewList.GroupBy(x => x.RestaurantId, x => new {x.RestaurantId,x.Rating})
.Join(restaurantList, x => x.Key,y => y.RestaurantId,(x,y) => new {
Name = y.Name,
AvgRating = x.Average(s => s.Rating)
});
,因此仅会列出至少有一条评论的餐馆,否则您需要InnerJoin
使用LeftOuterJoin
,评价为0的餐厅< / p>
答案 2 :(得分:2)
我看到您的Restaurant
课程已经有ICollection<Review>
代表餐馆的评论。这可能是因为您使用实体框架或类似的东西。
拥有这样的集合使得不必使用连接:
var averageRestaurantReview = Restaurants
.Select(restaurant => new
.Where(restaurant => ....) // only if you don't want all restaurants
{
Name = restaurant.Name,
AverageReview = restaurants.Reviews
.Select(review => review.Rating)
.Average(),
});
实体框架将为您进行适当的连接。
如果您真的想要使用某些内容,那么您需要Enumerable.GroupJoin
var averageRestaurantReview = Restaurants
.GroupJoin(Reviews, // GroupJoin Restaurants and Reviews
restaurant => restaurant.Id, // From every restaurant take the Id
review => review.RestaurantId, // From every Review take the RestaurantId
.Select( (restaurant, reviews) => new // take the restaurant with all matching reviews
.Where(restaurant => ....) // only if you don't want all restaurants
{ // the rest is as before
Name = restaurant.Name,
AverageReview = reviews
.Select(review => review.Rating)
.Average(),
});