加入和分组两个表并获得字段总和 - Linq C#

时间:2018-03-03 08:21:23

标签: c# linq

我的产品有两个表,一个与主仓相关,另一个与小商店有关。两个表都保留了产品数量。

tblWareHouse
-----------------------------------
ProductID   ProductSeries    Amount
   1           600             80
   1           601             50
   2           300             90

tblStore
-----------------------------------
ProductID   ProductSeries    Amount
   1           700             20
   1           601             40
   2           400             10

每个产品都有唯一的ProductSeries编号。我需要加入并对这两个表进行分组,并按照ProductID为两个仓库和商店获得数量的产品总和,如下所示:

Output
------------------------------------------
ProductID   StoreAmount    WareHouseAmount
    1          60               130
    2          10                90

我的代码是这样的:

var q = from d in db.tblWareHouses
         join s in db.tblStores on d.ProductID equals s.ProductID
         group new { d, s } by d.ProductID into v
         select new
         {
             ID = Convert.ToInt32(v.Key),
             WareHouseAmount = v.Sum(x => x.d.Amount),
             StoreAmount = v.Sum(x => x.s.Amount),
         };

但是有一个问题,它会产生额外的输出行,同时总结它会给我更多的数量。例如,对于仓库中的ProductID 1,它将在连接中生成3行存储,而在求和时,它将对所有额外行进行求和。我需要删除重复的。希望我足够清楚。如何解决?

2 个答案:

答案 0 :(得分:1)

由于每个表中的总和,我能够通过将总和分成单独的查询来实现:

var q1 = tblWareHouses.AsEnumerable()
    .GroupBy(r => r.ProductID)
    .Select(a => new
    {
        ProductID = a.Key,
        Amount = a.Sum(r => r.Amount)
    }).ToList();


var q2 = tblStores.AsEnumerable()
    .GroupBy(r => r.ProductID)
    .Select(a => new
    {
        ProductID = a.Key,
        Amount = a.Sum(r => r.Amount)
    }).ToList();

var q3 = (from d in q1
    join s in q2 on d.ProductID equals s.ProductID
    group new {d, s} by d.ProductID
    into v
    select new
    {
        ID = v.Key,
        WareHouseAmount = v.Sum(x => x.d.Amount),
        StoreAmount = v.Sum(x => x.s.Amount),
    }).ToList();

<强>输出:

enter image description here

答案 1 :(得分:0)

加入很可能像具有相同ProductID的行之间的笛卡尔连接一样工作,因此会产生错误的结果。我会尝试放弃加入和分组,而是使用Zip()。它从两个集合连接中获取相应的行,然后与新结果一起使用。它远非理想的解决方案,因为它很可能会评估计算机的内存。我认为你可以用sql避免这种情况,但是每个表都需要首先投射到包含行号的集合(即使用RANK函数),然后连接需要在这个行号上。