SQL左外连接,groupby& orderby到LINQ方法查询或方法语法

时间:2012-12-03 23:13:56

标签: c# sql linq entity-framework join

主要目标是根据受欢迎程度(按人数最多为特定成分的人数表示)按排序顺序返回成分列表。 SQL等价物如下:

select distinct COUNT(PersonalInfoes.FavoriteIngredient_ID) as NoUsing, 
Ingredients.Name 
from PersonalInfoes  right join Ingredients
on PersonalInfoes.FavoriteIngredient_ID = Ingredients.ID
group by Ingredients.Name
order by NoUsing desc

与上面产生相同结果的方法语法的等效SQL查询是什么? 我最接近的是:

from i in db.Ingredients 
join p in db.PersonalInfos on i.ID equals p.FavoriteIngredient.ID into ing
from p in ing.DefaultIfEmpty()
group i by i.Name into g
from p in g
orderby g.Count() descending
select new { Name = g.Key, Count = g.Count() }.Name;

1 个答案:

答案 0 :(得分:2)

您的查询执行左外连接以包含没有收藏夹的成分。问题是,对于没有收藏夹的每种成分,您要计算DefaultIfEmpty()生成的单个值。您可以在计算时排除默认值:

orderby g.Count(x => x != null) descending

您实际上不必执行左连接。您可以将组加入中的组计数加起来:

from i in db.Ingredients 
join p in db.PersonalInfos on i.ID equals p.FavoriteIngredient.ID into faves
group faves.Count() by i.Name into faveCounts
let count = faveCounts.Sum()
orderby count descending
select new { Name = faveCounts.Key, Count = count };

您的代码存在主观问题,因为它对所有group byfrom子句都非常困惑。如果您发现这是一个问题,您可以尝试使用更多描述性名称,使用子查询或使用方法语法。

编辑:这是方法语法版本。它不是来自查询语法版本的直接转换,因为那将非常难看。

db.Ingredients
  .GroupJoin(db.PersonalInfos,
             i => i.ID,
             p => p.ID, 
             (i, g) => new { i.Name, FaveCount = g.Count() })
  .GroupBy(x => x.Name,
           (key, grp) => new { Name = key, Count = grp.Sum(y => y.FaveCount) })
  .OrderByDescending(x => x.Count);