【问题标题】:Select value from group with the highest count从具有最高计数的组中选择值
【发布时间】:2015-02-06 04:09:27
【问题描述】:

假设我有两套;糖果和地区。对于每个 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; }
}

【问题讨论】:

  • 你提到你有两套。通过您的代码 sn-p,糖果对象包含糖果区域的集合,对吗?如果是这种情况,从技术上讲,您有一个包含一个集合的对象,而不是两个单独的集合,这意味着您需要某种形式的连接子句。
  • @JamesShaw 是的,CandyRegion 是关于 Candy 和 Region 的集合。地区将是第二组。 CandyRegion 加入了 Candy 和 Region。
  • @DamonPollard 我认为您还应该发布有问题的 Candy 和 Region 课程!它造成混乱..
  • 额外的 sn-p 绝对可以更轻松地确定您要完成的工作以及如何完成。
  • Candy 到 Region 似乎可以是多对多的关系。为什么要添加第三个 CandyRegion?是不是可以贴多区域糖果和多糖果区域?

标签: c# linq entity-framework


【解决方案1】:

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

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 进行比较。

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

【讨论】:

    【解决方案2】:

    在您可以拥有 c.CandyRegion 的同时查询 context 以获得计数的任何具体原因?

    下面的查询将导致连接,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();
    

    【讨论】:

    • 这会让我得到最受欢迎的糖果(大多数地区的糖果),而不是糖果最多的地区。我想找到后者。
    • @DamonPollard 查询的哪一部分让你认为这会给你糖果实例而不是 candyregion 实例?
    • 对不起,我的意思是关于您所做的更改,而不是查询的结果。 c.CandyRegion.Count() 会给我区域最多的糖果,导致顺序错误。
    • @DamonPollard 是将 Candy 与 Candy 表中的区域关联起来的 regionId 外键吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    相关资源
    最近更新 更多