如何用SQL+C#获取按年份筛选的Top10高频Error_Number及对应数量
解决方案
1. 完善SQL查询语句
需要补充年份筛选、出现次数统计、排名逻辑,同时支持按年份过滤,还可根据需求选择是否允许并列排名:
版本1:支持并列排名(同次数错误共享排名)
如果希望出现次数相同的错误号拥有同一排名,使用RANK()函数:
SELECT Error_Number, COUNT(*) AS Amount, RANK() OVER(ORDER BY COUNT(*) DESC) AS Error_Rank FROM [Table] WHERE YEAR(Date) = @TargetYear GROUP BY Error_Number ORDER BY Amount DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
版本2:严格唯一排名(无并列)
如果要求每个错误号排名唯一(即使次数相同),使用ROW_NUMBER()函数:
SELECT Error_Number, COUNT(*) AS Amount, ROW_NUMBER() OVER(ORDER BY COUNT(*) DESC) AS Error_Rank FROM [Table] WHERE YEAR(Date) = @TargetYear GROUP BY Error_Number ORDER BY Amount DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
注意:使用参数
@TargetYear替代硬编码年份,避免SQL注入,同时提升代码复用性。
2. C#代码实现
首先定义实体类映射查询结果:
public class ErrorStats { public int Error_Number { get; set; } public int Amount { get; set; } public int Error_Rank { get; set; } }
然后编写查询执行逻辑(采用参数化查询):
public List<ErrorStats> GetTop10ErrorsByYear(int targetYear) { var errorStatsList = new List<ErrorStats>(); string sql = @" SELECT Error_Number, COUNT(*) AS Amount, ROW_NUMBER() OVER(ORDER BY COUNT(*) DESC) AS Error_Rank FROM [Table] WHERE YEAR(Date) = @TargetYear GROUP BY Error_Number ORDER BY Amount DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;"; // 假设Database.getExecuteQuery支持传入参数,若不支持需重构为SqlCommand方式 using (var reader = Database.getExecuteQuery(sql, new SqlParameter("@TargetYear", targetYear))) { while (reader.Read()) { errorStatsList.Add(new ErrorStats { Error_Number = reader.GetInt32(reader.GetOrdinal("Error_Number")), Amount = reader.GetInt32(reader.GetOrdinal("Amount")), Error_Rank = reader.GetInt32(reader.GetOrdinal("Error_Rank")) }); } } return errorStatsList; }
3. 获取指定排名的错误数据
从返回的结果列表中直接筛选即可:
var top10Errors = GetTop10ErrorsByYear(2021); // 获取排名第1的错误 var rank1Error = top10Errors.FirstOrDefault(e => e.Error_Rank == 1); // 获取排名第2的错误 var rank2Error = top10Errors.FirstOrDefault(e => e.Error_Rank == 2); // 若使用RANK()函数,可能存在多个同排名错误,可批量获取 var allRank1Errors = top10Errors.Where(e => e.Error_Rank == 1).ToList();
优化说明
- 若
Date字段为索引列,建议将年份筛选改为范围查询以利用索引提升效率:
对应C#参数设置:WHERE Date >= @StartDate AND Date < @EndDatevar startDate = new DateTime(targetYear, 1, 1); var endDate = startDate.AddYears(1); - 确保查询使用参数化方式,避免SQL注入风险。
内容的提问来源于stack exchange,提问作者thisisforwork
相关产品推荐
相关产品推荐

