【问题标题】:How to query in EF core with OrderByDescending, Take, Select and FirstOrDefault如何使用 OrderByDescending、Take、Select 和 FirstOrDefault 在 EF 核心中进行查询
【发布时间】:2020-03-22 07:22:05
【问题描述】:

所以我有一个名为 Summaries 的表,它看起来像这样

我需要根据 CoveredDate 汇总 TotalPieces 的最新条目,并应按 ServiceCode 分组并按月查询 例如,ServiceCode 'A' 在 2020-01-01、2020-01-02、2020-01-03、2020-01-31、2020-02-01、2020-02-28、2020-02- 上有条目29 并且 ServiceCode 'B' 在 2020-01-01、2020-01-02、2020-01-31、2020-02-20、2020-02-21、 我需要根据月份获得总和,1 月“A”的最新条目是 2020 年 1 月 31 日,“B”的最新条目是 2020 年 1 月 31 日,我需要总结他们的“TotalPieces”,所以我应该得到 25 + 25 = 50。

基本上我需要做的是

  • 根据CoveredDate 和月/年获取所有最新条目
  • TotalPiecesServiceCode 相加

我得到了一个有效的查询,但这只是一种解决方法,因为我无法在查询时得到它。

            int sum_totalpieces = 0;
            foreach (var serviceCode in service_codes)
            {
                var totalpieces = _DbContext.ActiveSummaries.Where(acs =>
                                    acs.CoveredDate.Date.Month == query_month
                                    && acs.CoveredDate.Date.Year == query_year
                                    && acs.service_codes == serviceCode
                                    )
                    .OrderByDescending(obd => obd.CoveredDate)
                    .Take(1)
                    .Select(s => s.TotalPieces)
                    .ToList()
                    .FirstOrDefault();

                sum_totalpieces += totalpieces;
            }

service_codes 只是一个字符串列表

如果你们可以摆脱foreach 阻止他们并使其成为services_codes.Contains() 查询,或者另一种解决方法以使结果更快,那就太好了。非常感谢。

【问题讨论】:

  • 有没有机会将描述算法的 200 字句子分解成要点,以便更容易理解?说您想“仅对每个服务代码中最新(根据涵盖的日期)行的总数求和”是真的吗?
  • 不,等等……它是“每个(服务代码、月份)中仅最新(根据涵盖日期)行的总和”?
  • 可以用 GroupBy 替换循环。如果查询“慢”,则可能需要检查基础表布局和生成的查询计划。
  • 我的 where 子句只描述了月份、年份和服务代码。因为我需要按月查询
  • @user2864740 请不要在 cmets 中发布答案 - 将其充实为完整的答案,作为答案

标签: mysql sql entity-framework


【解决方案1】:

这会做到,但我认为它不会转换为 SQL 并在服务器上运行:

    _DbContext.ActiveSummaries
            .Where(b =>
                b.CoveredDate >= new DateTime(2020,1,1) &&
                b.CoveredDate < new DateTime(2020,2,1) && 
                new [] { "A", "B" }.Contains(b.ServiceCode)
            )
            .GroupBy(g => g.ServiceCode)
            .Sum(g => g.OrderByDescending(gb=> gb.CoveredDate).First().TotalPieces);


如果您想将其作为原始 SQL 执行以获得最佳性能,则如下所示:

SELECT SUM(totalpieces)
FROM 
  x 
  INNER JOIN 
  (
    SELECT servicecode, MAX(covereddate) cd 
    FROM x 
    WHERE x.servicecode IN ('A','B') AND covereddate BETWEEN '2020-01-01' AND '2020-01-31'
  )y ON x.servicecode=y.servicecode and x.covereddate = y.cd

【讨论】:

  • 试过了,但抛出了这个错误,处理 LINQ 表达式 'AsQueryable(OrderByDescending( 来源:NavigationTreeExpression Value: default(IGrouping) 表达式: (未处理的参数:e),keySelector: (gb) => gb.CoveredDate))' by 'NavigationExpandingExpressionVisitor' 失败。这可能表示 EF Core 中的错误或限制。有关更多详细信息,请参阅go.microsoft.com/fwlink/?linkid=2101433
  • 尝试将.ToList() 放在 Where() 之后/groupby 之前。我希望它不能被翻译成sql;列出它将下载行,其余操作将在本地进行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 1970-01-01
相关资源
最近更新 更多