从具有最高计数的组中选择值

时间:2015-02-06 04:09:28

标签: c# linq entity-framework

说我有两套;糖果和地区。对于每个Candy,我都会在某个区域(CandyRegion)中有一个叫做糖果的一对多名称。

我想构建一个Candy对象列表,其中只选择了一个CandyRegion.Name。选择的CandyRegion.Name由最受欢迎的区域(该区域中可用的糖果数量最多)确定。

什么是一种合适的方式来执行查询以找到最受欢迎的区域?到目前为止我所拥有的:

context.Candys
    .Select(c => c.CandyRegions
        .OrderByDescending(cr => 
            /* 
             * Order CandyRegion by Candy.CandyRegion.Count outside
             * the context of c? 
             */
            context.CandyRegions.Count(cr2 => cr2.RegionId == cr.RegionId)
        )
        .FirstOrDefault()
    )
    .ToList();

我觉得上述查询的性能会出现问题。

编辑:课程

public class Candy
{
    public int Id { get; set; }
    ...

    public virtual List<CandyRegion> CandyRegions { get; set; } 
}

public class Region
{
    public int Id { get; set; }
    ...

    public virtual List<CandyRegion> CandyRegions { get; set; } 
}

public class CandyRegion
{
    public int Id { get; set; }
    public string Name { get; set; }
    ...

    public int RegionId { get; set; }
    public virtual Region Region { get; set; }

    public int CandyId { get; set; }
    public virtual Candy Candy { get; set; }
}

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题,虽然我还没有测试过。让我知道这可以解决您的问题。

Context.Candys
                .Where(c => c.Id == c.CandyRegions
                    .FirstOrDefault(cr => cr.RegionId == c.CandyRegions
                        .GroupBy(grp => grp.RegionId)
                            .Select(r => new
                                            {
                                                RegionId = r.Key,
                                                Total = r.Count()
                                            }
                                    ).OrderByDescending(r => r.Total)
                                                .Take(1)
                                                .First().RegionId
                                    ).CandyId
                        )
                        .ToList();

解释上面发生的事情......

由于Region和Candy都使用CandyRegion作为桥接表,您可以通过它的RegionId将Candy的外键集合CandyRegion分组。

这提供了一种确定每个分组集的计数的简便方法。既然你有计数,我们想要从最高到最低排序,并抓住最顶层的项目。我们不关心其余的事情。

一旦完成,只需选择列表中包含的第一个与确定的RegionId相匹配的CandyRegion,然后将它的CandyId与同一CandyRegion的CandyID进行比较。

最后,当这一切都完成后,你将结果作为一个列表返回,这就是你所追求的糖果。

答案 1 :(得分:0)

查询context以获取计数的任何具体原因,而您可以随身携带c.CandyRegion吗?

以下查询将导致加入并使用context进行查询将导致内部查询。

context.Candy
    .Select(c => c.CandyRegion
        .OrderByDescending(cr => 
            /* 
             * Order CandyRegion by Candy.CandyRegion.Count outside
             * the context of c? 
             */
            c.CandyRegion.Count()
        )
        .FirstOrDefault()
    )
    .ToList();