C# Linq分组统计求助:全商品库存计算查询优化
问题解决方案
问题根源分析
- 仅显示有入库记录的商品:原查询用了内连接
join stock in _context.Stocks,会直接过滤掉无入库记录的商品,需改为左外连接保留所有商品。 - 售出数量显示错误:原分组后用
g.Select(x => x.sold).Count(),因左连接后产生重复数据,导致计数结果异常,需先对售出记录按商品编码聚合统计。
修正后的LINQ查询
return await (from product in _context.Products // 左外连接库存表,确保所有商品都被包含 join stock in _context.Stocks on product.Id equals stock.ProductId into stockGroup from subStock in stockGroup.DefaultIfEmpty() // 先对售出记录按商品编码分组,统计每个商品的售出条数 join sold in (from so in _context.SaleProducts group so by so.Code into sg select new { ProductCode = sg.Key, SoldCount = sg.Count() }) on product.Code equals sold.ProductCode into soldGroup from subSold in soldGroup.DefaultIfEmpty() // 按商品分组,聚合库存和售出数据 group new { subStock, subSold } by product into g select new StockViewModel { ProductId = g.Key.Id, ProductCode = g.Key.Code, ProductName = g.Key.Name, // 无入库记录时库存总和取0 StockAdded = g.Sum(x => x.subStock?.Quantity ?? 0), // 无售出记录时售出数量取0 ItemsSold = g.Select(x => x.subSold?.SoldCount ?? 0).FirstOrDefault(), // 计算剩余库存 RemainingStock = g.Sum(x => x.subStock?.Quantity ?? 0) - g.Select(x => x.subSold?.SoldCount ?? 0).FirstOrDefault() }) .ToArrayAsync();
关键调整说明
- 左外连接库存表:通过
into stockGroup搭配DefaultIfEmpty(),保留所有商品条目,不管是否有入库记录。 - 预聚合售出数据:提前对
SaleProducts按商品编码分组统计售出数量,避免关联后数据重复导致计数错误。 - 空值兜底处理:用
?? 0处理无库存或无售出记录的场景,既避免空引用异常,也保证数值计算的正确性。
内容的提问来源于stack exchange,提问作者Trystan Lapinig-Wilcock
相关产品推荐
相关产品推荐

