简体   繁体   English

用LINQ连接数据表,选择多列,然后按多列分组求和

[英]Join datatables with LINQ, select multiple columns and sums with group by multiple columns

I am joining two datatables with LINQ and trying to select data from both tables, including sum of one column grouped by two columns. 我将两个数据表与LINQ联接在一起,并尝试从两个表中选择数据,包括将一列和两列分组的总和。 The data structure seems like this. 数据结构看起来像这样。

table1 (Demands)
  propertyID
  propertyGroupID
  supplierID
  demand

propertyID  |propertyGroupID    |supplierId |demand |ContractId
13          |3                  |3          |2      |1
22          |4                  |3          |1      |1
21          |5                  |3          |12     |1
15          |5                  |3          |3      |1
16          |7                  |3          |16     |1
23          |5                  |3          |5      |1


table2 (Supplies)
  supplierID
  propertyID
  supply

supplierId  |propertyID |supply
4           |23         |2764
1           |22         |3521
1           |16         |2533
11          |23         |876
4           |21         |5668

I would like to have the result as 我想得到的结果是

supplierID
propertyGroupID
sum(supply)
sum(demand)

These would be grouped by supplierID and propertyGroupID. 这些将按SupplierID和propertyGroupID分组。 So, finally I would like to compare actual supplies to the demand by each supplier and property group. 因此,最后我想将实际供应与每个供应商和房地产集团的需求进行比较。

What I have done so far is 到目前为止,我所做的是

var result = from demandItems in table1.AsEnumerable()
             join supplyItems in table2.AsEnumerable() on
Convert.ToInt16(demandItems["propertyID"]) equals 
Convert.ToInt16(supplyItems["propertyID"])
             group new
             {
                demandItems,
                supplyItems
            }
            by new
            {
                Supplier = supplyItems.Field<string>("supplierID"),
                PropertyGroup = demandItems.Field<int>("propertyGroupID")
            }
            into groupDt
             select new
             {
                SupplierID = groupDt.Key.Supplier,
                PropertyGroupId = groupDt.Key.PropertyGroup,
                SumOfSupply = groupDt.Sum(g => g.supplyItems.Field<double>("supply")),
            SumOfDemand = groupDt.Sum(g => g.demandItems.Field<double>("demand"))
        };

This works fine and I get correct sum of supply grouped by different suppliers and property groups. 这很好,我得到了按不同供应商和资产组分组的正确供应量总和。 However, the sum of demand is not correct. 但是,需求总和是不正确的。

SupplierID  |PropertyGroupID    |SumOfSupply    |SumOfDemand
4           |5                  |8432           |17
1           |4                  |3521           |1
1           |7                  |2533           |16
11          |5                  |876            |5

As you see, table1 has only one supplier (ID=3). 如您所见,表1只有一个供应商(ID = 3)。 The correct result data should be 正确的结果数据应为

SupplierID  |PropertyGroupID    |SumOfSupply    |SumOfDemand
4           |5                  |8432           |0
1           |4                  |3521           |0
1           |7                  |2533           |0
11          |5                  |876            |0
3           |3                  |0              |2
3           |4                  |0              |1              
3           |5                  |0              |20
3           |7                  |0              |16

How to obtain the result I want? 如何获得我想要的结果?

EDIT 2018-01-05 编辑2018-01-05

I'm using NetMage's solution to solve my problem. 我正在使用NetMage的解决方案来解决我的问题。 However, I get an error message from 但是,我收到一条错误消息

var result = from d in table1sum.Concat(table2sum)...

Error CS1929 'EnumerableRowCollection<>' does not contain a definition for 'Concat' and the best extension method overload 'Queryable.Concat<>(IQueryable<>, IEnumerable<>)' requires a receiver of type 'IQueryable<>' 错误CS1929'EnumerableRowCollection <>'不包含'Concat'的定义,最佳扩展方法重载'Queryable.Concat <>(IQueryable <>,IEnumerable <>)'需要类型为'IQueryable <>的接收器

Is this propably due to the fact that my original tables are actually read from database? 这是否可能是因为实际上我的原始表实际上是从数据库中读取的?

DataTable table1 = DemandDataSet.Tables[0];
DataTable table2 = SupplyDataSet.Tables[0];

For example, I had to use notation 例如,我必须使用符号

var table1sum = table1.AsEnumerable().Select(d => new
            { propertyGroupID = (int)d["propertyGroupID"],
            supplierId = (int)d["supplierId"],
            demand = (double)d["demand"],
            supply = 0 });

Edit 2 2018-01-05 编辑2 2018-01-05

The error was due to type differences between fields in tables table1sum and table2sum. 该错误是由于表table1sum和table2sum中的字段之间的类型差异引起的。 Specifically, fields "supply" and "demand" had different types in comparing tables. 具体来说,比较表中的字段“供应”和“需求”具有不同的类型。 When I changed 当我改变

demand = 0.0

and

supply = 0.0

compiler found .Concat -method. 编译器找到.Concat方法。

Your data tables are not normalized, which I think is causing your issue. 您的数据表未规范化,我认为这是导致您出现问题的原因。 You don't really want to combine the supply and demand tables. 您实际上并不想合并供需表。

First, summarize the demand table to the information needed for the result: 首先,将需求表汇总为结果所需的信息:

var table1sum = table1.AsEnumerable().Select(d => new { d.propertyGroupID, d.supplierId, d.demand, supply = 0 });

Second, summarize the supply table to the information needed for the result, using the demand table to get the propertyGroupID needed: 其次,使用需求表来获取所需结果信息的供应表,以获取所需的propertyGroupID

var table2sum = from supplyItem in table2.AsEnumerable()
                join demandItem in table1.AsEnumerable() on supplyItem.propertyID equals demandItem.propertyID
                select new {
                    demandItem.propertyGroupID,
                    supplyItem.supplierId,
                    demand = 0,
                    supplyItem.supply
                };

Now you can combine the summaries and group to get the desired result: 现在,您可以将摘要和组组合以获得所需的结果:

var result = from d in table1sum.Concat(table2sum)
             group d by new { d.supplierId, d.propertyGroupID } into dg
             select new {
                 SupplierID = dg.Key.supplierId,
                 PropertyGroupId = dg.Key.propertyGroupID,
                 SumOfSupply = dg.Sum(g => g.supply),
                 SumOfDemand = dg.Sum(g => g.demand)
             };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM