0

我有一个查询,它必须对几个表中的值求和并添加结果。该系统只是一个库存系统,我试图通过计算进货 ( 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 的答案中获取代码,稍作改动。每个lets 都可以返回 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);
4

3 回答 3

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;
于 2013-07-01T13:26:42.710 回答
0

您是否考虑过向数据库添加一个视图来执行计算,然后您可以使用简单的选择查询(或 SP)来返回您需要的值?

于 2013-07-01T13:00:59.387 回答
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);
    }
}
于 2013-07-01T13:25:15.953 回答