基于LINQ查询按年份计算SourceId使用占比的技术需求
按年份计算SourceId使用占比的LINQ实现方案
没问题,我来帮你搞定这个按年份统计各SourceId使用占比的需求!下面是具体的实现思路和代码示例:
第一步:明确需求逻辑
我们需要先统计每个年份的总数据量,再用每个SourceId在该年份的记录数除以年度总数,得到占比(这里按你的示例取整数,比如63%就存63)。
第二步:定义结果实体类
首先我们需要一个类来承载最终的统计结果:
public class SourceUsagePercent { public int Year { get; set; } public int SourceId { get; set; } public int Percent { get; set; } // 若需要保留小数,可改为double类型 }
第三步:LINQ实现(内存集合版本)
假设你已经有了包含Year和SourceId字段的原始数据集合(比如叫sourceUsageRecords),可以分三步完成计算:
// 1. 按【年份+SourceId】分组,统计每组的记录数 var yearlySourceCounts = sourceUsageRecords .GroupBy(record => new { record.Year, record.SourceId }) .Select(group => new { group.Key.Year, group.Key.SourceId, Count = group.Count() }) .ToList(); // 2. 按年份分组,计算每个年度的总记录数 var yearlyTotals = yearlySourceCounts .GroupBy(item => item.Year) .Select(group => new { Year = group.Key, Total = group.Sum(x => x.Count) }) .ToList(); // 3. 关联两组数据,计算占比并转为目标格式 var finalResult = yearlySourceCounts .Join(yearlyTotals, sourceCount => sourceCount.Year, yearlyTotal => yearlyTotal.Year, (sourceCount, yearlyTotal) => new SourceUsagePercent { Year = sourceCount.Year, SourceId = sourceCount.SourceId, Percent = (int)Math.Round((double)sourceCount.Count / yearlyTotal.Total * 100) }) .OrderBy(result => result.Year) .ThenBy(result => result.SourceId) .ToList();
第四步:EF Core数据库查询版本(性能优化)
如果你的数据来自数据库,推荐直接在数据库层面做聚合计算,避免拉取全量数据到内存:
var finalResult = await ( from record in _context.SourceUsageRecords group record by new { record.Year, record.SourceId } into sourceGroup select new { sourceGroup.Key.Year, sourceGroup.Key.SourceId, Count = sourceGroup.Count() } into sourceCount join yearlyTotal in ( from record in _context.SourceUsageRecords group record by record.Year into yearGroup select new { Year = yearGroup.Key, Total = yearGroup.Count() } ) on sourceCount.Year equals yearlyTotal.Year select new SourceUsagePercent { Year = sourceCount.Year, SourceId = sourceCount.SourceId, Percent = (int)Math.Round((double)sourceCount.Count / yearlyTotal.Total * 100) }) .OrderBy(result => result.Year) .ThenBy(result => result.SourceId) .ToListAsync();
关键说明
Math.Round用于对占比进行四舍五入取整,如果你不需要取整,可以去掉强制转int,把Percent字段改为double;- 最后排序是为了让结果按年份和SourceId有序展示,方便查看;
- 如果你的现有LINQ已经得到了
yearlySourceCounts这一步的结果,可以直接从第二步开始执行。
内容的提问来源于stack exchange,提问作者Bronzato
相关产品推荐
相关产品推荐

