0

複数のテーブルの値を合計して結果を追加する必要があるクエリがあります。deliveriesこのシステムは単純な在庫システムであり、入庫 ( )、出庫 ( issues)、および品目を計算して在庫レベルを取得しようとしadjustmentsています。

在庫レベルは計算値(sum(deliveries) - sum(issues)) + sum(adjustments)であるため、最小限のクエリでこの値を取得する関数を作成しようとしています。

現在、3 つの個別のクエリを実行して各合計値を取得し、関数で加算/減算を実行する linq がありますが、3 つの個別のクエリを実行することなく値を計算するためのより良い方法が必要であると確信しています。

現在の機能は次のとおりです。

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 を返す可能性があり、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

これでうまくいくと思いますし、生成された 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 に答える