【问题标题】:Converting SQL to Linq with groupby, sum and count使用 groupby、sum 和 count 将 SQL 转换为 Linq
【发布时间】:2014-07-01 14:19:14
【问题描述】:

我想根据一个总和和一个计数来做一个分组。我似乎无法在 linq 中创建解决方案。如何将我的查询转换为 linq?

SELECT HistoricalBillingProductGroup, 
        COUNT(*), 
        BillingPeriod, 
        SUM(TotalMonthlyChargesOtcAndMrc)
FROM [x].[dbo].[tblReport]
group by BillingPeriod, HistoricalBillingProductGroup
order by BillingPeriod

这是我迄今为止在 Linq 中得到的结果

var result =
    context.Reports.GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
            .Select(x => new StatisticsReportLine
                {
                    HistoricalBillingGroup = x.FirstOrDefault().HistoricalBillingProductGroup,
                    BillingPeriod = x.FirstOrDefault().BillingPeriod,
                    CountOfRows = x.Count(),
                    SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
                })
            .ToString();

我从中得到的查询非常庞大,需要很长时间才能加载。在 SQL 中,它只需几毫秒。我几乎不怀疑这是解决方案。

【问题讨论】:

  • context.Reports的类型是什么?你看过生成的 SQL 了吗?
  • 我从我的代码优先域上下文中获取报告,生成的 SQL 就像答案所说的带有一些子查询。我猜这就是它变慢的原因。

标签: c# sql sql-server linq


【解决方案1】:

我相信对x.FirstOrDefault() 的调用是您问题的根源。这些中的每一个都将导致在生成的 SQL 的 SELECT 子句中进行非常昂贵的内部查询。

尝试改用IGrouping<T>Key 属性:

var result = context.Reports
    .GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
    .OrderBy(x => x.Key.BillingPeriod)
    .Select(x => new StatisticsReportLine
        {
            HistoricalBillingProductGroup = x.Key.HistoricalBillingProductGroup,
            BillingPeriod = x.Key.BillingPeriod,
            CountOfRows = x.Count(),
            SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
        });

或者,如果您更喜欢查询语法:

var result =
    (from r in context.Reports
     group r by new { r.BillingPeriod, r.HistoricalBillingProductGroup } into g
     orderby g.Key.BillingPeriod
     select new StatisticsReportLine
     {
         HistoricalBillingProductGroup = g.Key.HistoricalBillingProductGroup,
         BillingPeriod = g.Key.BillingPeriod,
         CountOfRows = g.Count(),
         SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
     });

【讨论】:

  • 感谢您的回答,我个人更喜欢非查询语法。
  • @Freddy 没问题。对于非常短的查询,我更喜欢流畅的语法,而对于更长、更复杂的查询,我更喜欢使用流畅的语法,但这真的是个人喜好问题。快乐编码:)
【解决方案2】:

你可以试试这个:

var result = context.Reports
                    .GroupBy(x => new {x.BillingPeriod, x.HistoricalBillingProductGroup})
                    .Select(x => new StatisticsReportLine
                    {
                        HistoricalBillingGroup = x.Key.HistoricalBillingProductGroup,
                        BillingPeriod = x.Key.BillingPeriod,
                        CountOfRows = x.Count(),
                        SumOfAmount = x.Sum(p => p.TotalMonthlyChargesOtcAndMrc) ?? 0
                    }).ToString();

在上述查询中,您根据BillingPeriodHistoricalBillingProductGroup 这两个属性进行分组。因此,在将要创建的每个组中,您将拥有一个由这两个属性组成的密钥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-17
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 2011-03-25
    • 1970-01-01
    相关资源
    最近更新 更多