一、需求
需要查询A物料在对应年份中每个月的总数量和总重量,显示在echarts图表上,其中X轴的数据为对应年份+12个月份;y轴数据是重量和数量数据。
二、确定后端返回实体对象结构
public class BalanceMonthOutput
{
/// <summary>
/// X轴数据 月份
/// </summary>
public List<string> XDataListYearMonth { get; set; }
/// <summary>
/// 物料件数
/// </summary>
public List<decimal> MaterialQty { get; set; }
/// <summary>
/// 物料重量
/// </summary>
public List<decimal> MaterialTon { get; set; }
}
三、查询语句逻辑
首先数据库里的数据字段有:物料编码、日期(yyyy-MM-dd形式)、重量、数量。
首先是查对应年份的每个月的汇总重量和数量,所以需要使用sum()函数对重量、数量进行求和计算,使用Year(日期)、Month(日期)获取到对应的年份、月份,最后使用group by 年,月,物料即可,所以sql如下:
SELECT
YEAR( NowDateTime ) as year,
MONTH(NowDateTime) as month,
MateriaCode,
SUM(Quantity) as qty,
SUM(Ton) as ton
FROM
goodsTable
where YEAR( NowDateTime ) =@year and MateriaCode=@materiaCode
GROUP BY YEAR( NowDateTime ),MONTH(NowDateTime),MateriaCode
ORDER BY year,month
四、将数据库查询出的数据处理成返回的实体对象
首先明确数据库返回的数据结构,因为我们不确定数据库中的物料在12个月中每个月都有数据记录,但是可以确定的是数据记录不会超过12条。
我们前端的y轴数据,需要两个集合,存放12个月份的重量和数量,按照月份进行排序,所以定义两个长度为12默认值为0的集合,问题点在于,因为数据库数据可能只有6月份,也可能有1 2 8 月份的,所以怎么将对应的月份数据填充到对应的索引位置上去,因为我们12个月份是固定的1-12月,即它的索引下标为0-11,这就给我们提供了很大的思路,我们不管数据库中存在那几个月的数据,数据中肯定会存在对应的月份,我们用数字类型接收,此时,我们只需要循环数据库查询出来的数据,将数据中的月份-1作为数组下标,将对应的数量填充进去即可。
业务代码如下:
//获取到表中存在的月份的汇总数据
List<BalanceMonthDto> results = _rep.Context.CopyNew().Ado.SqlQuery<BalanceMonthDto>(querySql,year, materiaCode);
decimal[] qtyArray = new decimal[12];
decimal[] tonArray = new decimal[12];
// 遍历列表,将数量填充到数组的对应月份索引中
foreach (var mq in results)
{
// 确保月份在有效范围内
if (mq.month >= 1 && mq.month <= 12)
{
qtyArray[mq.month - 1] = mq.qty; // 数组索引从0开始,所以月份需要减1
tonArray[mq.month - 1] = mq.ton;
}
}
output.MaterialQty = qtyArray.ToList();
output.MaterialTon = tonArray.ToList();
五、返回前端,填充数据,显示图表。
附:echarts显示当前年份以及前4年的数据。
这个时候,数据库里面查出来的就是各年份的数据,一样的逻辑,需要显示前4前每年的某物料汇总数量,也定义一个长度为5,默认值为0的集合。然后我们循环数据库查询出来的记录,每一次循环时,用当前年份减去数据年份,得出来的数值判断是否在0-4之间,如果在范围中,那么将计算出来的差值作为集合的下标,并将对应的数量、重量存储进去。例如:当前年份为2024,数据库某条记录为2021,那么差值为3,在0-4之间,那么将其作为下标进行插入,假设该数据对应的重量为100,那么重量的集合应该为:[0,0,0,3,0]
循环结束后对集合进行反转,即从小到大年份排序。具体代码如下:
List<BalanceMonthDto> results = _rep.Context.CopyNew().Ado.SqlQuery<BalanceMonthDto>(querySql, year, materiaCode);
decimal[] qtyArray = new decimal[5];
decimal[] tonArray = new decimal[5];
//获取当前年份以及5年前的年份
if (input.Date!=null)
{
int intYear = input.Date.ToInt();
// 遍历列表,将数量填充到数组中
foreach (var yq in results)
{
// 计算年份与当前年份的差值,然后转换为数组索引(注意索引从0开始)
int index = intYear - yq.year;
// 检查索引是否在有效范围内(0到4)
if (index >= 0 && index < qtyArray.Length)
{
qtyArray[index] = yq.qty;
tonArray[index] = yq.ton;
}
// 注意:如果年份早于4年前或晚于今年,上面的条件将不会执行,数组中的相应位置将保持为0
}
}
output.MaterialQty = qtyArray.Reverse().ToList();
output.MaterialTon = tonArray.Reverse().ToList();