简体   繁体   English

linq加入,分组和父级汇总

[英]linq joining, grouping, with parent roll-up

say I've got a DataTable in this format: 说我有这种格式的数据表:

id | key1 | key2 | data1 | data2 | parentID
10 |  AA  | one  |  10.3 |   0.3 |  -1
10 |  AA  | two  |  20.1 |  16.2 |  -1
10 |  BB  | one  |  -5.9 |  30.1 |  -1
20 |  AA  | one  | 403.1 | -20.4 |  10
30 |  AA  | one  | 121.5 | 210.3 |  -1

and a second DataTable like so: 第二个DataTable像这样:

id | data
10 |  5500
20 | -3000
30 |   500

what I want to do is aggregate the data at the "id" level, with the second table's "data" field added to the first's net "data1", and "data2" just summed up by itself. 我想做的是在“ id”级别聚合数据,将第二个表的“ data”字段添加到第一个表的净“ data1”中,而“ data2”只是自己汇总。 I figured out how to do this, but what I'm stuck at is this: I want data for anything with "parentID" != -1 to be added to it's parent. 我想出了如何做到这一点,但我遇到的问题是:我希望将任何带有“ parentID”!= -1的数据添加到其父项中。 so the output of the above data should be 因此上述数据的输出应为

id | data1   | data2
10 | 2927.6  |  26.2
30 |  621.5  | 210.3

is there an efficient way to do this? 有没有一种有效的方法可以做到这一点?

edit: code sample 编辑:代码示例

        DataTable dt1 = new DataTable();
        dt1.Columns.Add("id", typeof(int));
        dt1.Columns.Add("key1", typeof(string));
        dt1.Columns.Add("key2", typeof(string));
        dt1.Columns.Add("data1", typeof(double));
        dt1.Columns.Add("data2", typeof(double));
        dt1.Columns.Add("parentID", typeof(int));

        DataTable dt2 = new DataTable();
        dt2.Columns.Add("id", typeof(int));
        dt2.Columns.Add("data", typeof(double));

        dt1.Rows.Add(new object[] { 10, "AA", "one", 10.3, 0.3, -1 });
        dt1.Rows.Add(new object[] { 10, "AA", "two", 20.1, 16.2, -1 });
        dt1.Rows.Add(new object[] { 10, "BB", "one", -5.9, 30.1, -1 });
        dt1.Rows.Add(new object[] { 20, "AA", "one", 403.1, -20.4, 10 });
        dt1.Rows.Add(new object[] { 30, "AA", "one", 121.5, 210.3, -1 });

        dt2.Rows.Add(new object[] { 10, 5500 });
        dt2.Rows.Add(new object[] { 20, -3000 });
        dt2.Rows.Add(new object[] { 30, 500 });

        var groups = dt1.AsEnumerable()
                        .GroupBy(e => e["id"])
                        .Select(e => new
                                     {
                                         id = e.Key,
                                         net_data1 = e.Sum(w => (double)w["data1"]),
                                         net_data2 = e.Sum(w => (double)w["data2"])
                                     })
                        .GroupJoin(dt2.AsEnumerable(), e1 => e1.id, e2 => e2["id"],
                                   (a1, a2) => new
                                               {
                                                   id = a1.id,
                                                   net_data1 = a1.net_data1 + a2.Sum(w => (double)w["data"]),
                                                   net_data2 = a1.net_data2
                                               });

Unfortunately, SQL (and, by extension, LINQ) is not well-suited to recursion. 不幸的是,SQL(以及扩展名LINQ)并不适合于递归。 Can the parentID column go multiple levels deep? parentID列可以深入多个层次吗? Like this: 像这样:

ID     Parent
------------------
10     -1
20     10
30     10
40     20

If you want to retrace the steps up from ID 40 to ID 10, then you should abandon a SQL/LINQ approach and just do it in code. 如果要追溯从ID 40到ID 10的步骤,则应该放弃SQL / LINQ方法,而只需用代码即可。

It sounds like a good use of a group join. 听起来好像很好地使用了组联接。 Something like this might work (though it's completely untested): 像这样的事情可能会起作用(尽管它完全未经测试):

var items = from parent in context.dataTable
            join child in context.dataTable on parent.id equals child.parentID into children
            where parent.parentID == -1
            select new { id = parent.id, 
                         data1 = (parent.data1 + children.Sum(c => c.data1)), 
                         data2 = (parent.data2 + children.Sum(c => c.data2)) };

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

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