使用groupby,sum和count将SQL转换为Linq

时间:2014-07-01 14:19:14

标签: c# sql sql-server linq

我想做一个小组和一个总和和一个计数。我似乎无法在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中它只需几毫秒。我几乎不怀疑这是解决方案。

2 个答案:

答案 0 :(得分:3)

我相信拨打x.FirstOrDefault()的电话是您问题的根源。这些中的每一个都会在生成的SQL的SELECT子句中导致非常昂贵的内部查询。

请尝试使用IGrouping<T>的{​​{3}}属性:

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
     });

答案 1 :(得分: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进行分组。因此,在将要创建的每个组中,您将拥有一个密钥,该密钥将由这两个属性组成。