我有一个查询,必须对几个表中的值求和并添加结果。该系统只是一个库存系统,我试图通过计算项目的收入(deliveries
),支出(issues
)和adjustments
来获得库存水平。
由于库存水平是计算值(sum(deliveries) - sum(issues)) + sum(adjustments)
,我正在尝试创建一个函数,以最少的查询数量获得此值。
目前我有linq执行三个单独的查询来获取每个求和值,然后在我的函数中执行加法/减法,但是我确信必须有更好的方法来计算值而不必进行三个单独的查询
目前的功能如下:
public static int GetStockLevel(int itemId)
{
using (var db = EntityModel.Create())
{
var issueItemStock = db.IssueItems.Where(x => x.ItemId == itemId).Sum(x => x.QuantityFulfilled);
var deliveryItemStock = db.DeliveryItems.Where(x => x.ItemId == itemId).Sum(x => x.Quantity);
var adjustmentsStock = db.Adjustments.Where(x => x.ItemId == itemId).Sum(x => x.Quantity);
return (deliveryItemStock - issueItemStock) + adjustmentsStock;
}
}
在我看来,SQL查询非常简单,所以我考虑了一个存储过程,但是我认为必须有一种方法可以用linq来实现。
非常感谢
从Ocelot20的答案中获取代码,稍作修改。每个let
都可以返回null,如果是,则linq会抛出异常。使用DefaultIfEmpty
命令将取消此操作,并返回0以进行最终计算。我使用的实际代码如下:
from ii in db.Items
let issueItems = db.IssueItems.Where(x => x.ItemId == itemId).Select(t => t.QuantityFulfilled).DefaultIfEmpty(0).Sum()
let deliveryItemStock = db.DeliveryItems.Where(x => x.ItemId == itemId).Select(t => t.Quantity).DefaultIfEmpty(0).Sum()
let adjustmentsStock = db.Adjustments.Where(x => x.ItemId == itemId).Select(t => t.Quantity).DefaultIfEmpty(0).Sum()
select (deliveryItemStock - issueItems) + adjustmentsStock);
答案 0 :(得分:3)
不知道你的实体是什么样的,你可以这样做:
public static int GetStockLevel(int itemId)
{
using (var db = EntityModel.Create())
{
// Note: Won't work if there are no IssueItems found.
return (from ii in db.IssueItems
let issueItems = db.IssueItems.Where(x => x.ItemId == itemId)
.Sum(x => x.QuantityFulfilled)
let deliveryItemStock = db.DeliveryItems.Where(x => x.ItemId == itemId)
.Sum(x => x.Quantity)
let adjustmentsStock = db.Adjustments.Where(x => x.ItemId == itemId)
.Sum(x => x.Quantity)
select issueItems + deliveryItemStock + adjustmentsStock).FirstOrDefault() ?? 0;
}
}
我在自己的数据库上测试了一个类似的查询,它在一个查询中工作。我怀疑,因为他们都有一个共同的ItemId
,使用实体关系可以使它看起来像:
// Ideal solution:
(from i in db.Items
where i.Id == itemId
let issueItems = i.IssueItems.Sum(x => x.QuantityFulfilled)
let deliveryItemStock = i.DeliveryItems.Sum(x => x.Quantity)
let adjustmentsStock = i.Adjustments.Sum(x => x.Quantity)
select issueItems + deliveryItemStock + adjustmentsStock).SingleOrDefault() ?? 0;
答案 1 :(得分:0)
您是否考虑过向执行计算的数据库添加一个视图,然后您只需使用简单的选择查询(或SP)来返回所需的值?
答案 2 :(得分:0)
我认为这应该可行,并且生成的SQL并不是特别复杂。如果您认为它有问题,请告诉我,我会更新我的答案。
public static int GetStockLevel(int itemId)
{
using (var db = EntityModel.Create())
{
return db.IssueItems.Where(x => x.ItemId == itemId).GroupBy(x => x.ItemId)
.GroupJoin(db.DeliveryItems, x => x.First().ItemId, y => y.ItemId, (x, y) => new
{ Issues = x, Deliveries = y})
.GroupJoin(db.Adjustments, x=> x.Issues.First().ItemId, y=> y.ItemId, (x, y) => new
{
IssuesSum = x.Issues.Sum(i => i.QuantityFullfilled),
DeliveriesSum = x.Deliveries.Sum(d => d.Quantity),
AdjustmentsSum = y.Sum(a => a.Quantity)})
.Select(x => x.IssuesSum - x.DeliverysSum + x.AdjustmentsSum);
}
}