对相同的行进行分组并返回具有最大值的行的id

时间:2015-08-13 01:46:47

标签: vb.net linq grouping

我有一个如下数据:

id  desc    amt  value 1  value 2  value 3  value 4  count  Consolidated ID

1   test    23   78       98       30       13       5  
2   sample  14   25       45       36       12       24 
3   test    23   78       98       30       13       30 
4   sample  14   25       45       36       12       20 
5   test    23   78       98       30       13       11 

我需要

  1. 按列descamtvalue1value2value3value4以及
  2. 分组
  3. consolidated ID作为每个组的id列中具有最大值的count返回。结果集应如下所示:

     id  desc   amt  value 1  value 2  value 3  value 4  count  Consolidated ID
    
     1   test   23   78       98       30       13       5      3
     3   test   23   78       98       30       13       30     3
     5   test   23   78       98       30       13       11     3
     2   sample 14   25       45       36       12       24     2
     4   sample 14   25       45       36       12       20     2
    
  4. 我知道这可以通过数据表循环完成。但是有一种更简单的方法可以在1或2个语句中使用LINQ吗?

2 个答案:

答案 0 :(得分:2)

DataTable - dt

结果将是IEnumerable语句中匿名类型的Select类型,其列与您的DataTable

相同
var final = dt.AsEnumerable().GroupBy(x=>
                                      new {
                                            amt = x["amt"],
                                            value1 = x["value1"],
                                            value2 = x["value2"],
                                            value3 = x["value3"],
                                            value4 = x["value4"],                                              
                                         })
                          .ToDictionary(p=>p.Key,
                                        p=>new {id = p.Select(s=>s["id"]),
                                                cid = p.OrderByDescending(n=>Convert.ToInt32((n["count"]))).Select(s=>s["id"]).First()})
                          .SelectMany(a=>a.Value.id.Select(h=>new { 
                                    h,
                                    a.Key.amt,
                                   a.Key.value1,
                                   a.Key.value2,
                                   a.Key.value3,
                                   a.Key.value4,                                       
                                   ConsolidatedID = a.Value.cid
                                }));

同样粘贴VB.Net版本(使用Telerik Code Converter),虽然需要验证,但一直是争论的焦点,因为我在VB.Net中不起作用

Dim final = dt.AsEnumerable().GroupBy(Function(x) New With { _
    Key .amt = x("amt"), _
    Key .value1 = x("value1"), _
    Key .value2 = x("value2"), _
    Key .value3 = x("value3"), _
    Key .value4 = x("value4") _
}).ToDictionary(Function(p) p.Key, Function(p) New With { _
    Key .id = p.[Select](Function(s) s("id")), _
    Key .cid = p.OrderByDescending(Function(n) Convert.ToInt32((n("count")))).[Select](Function(s) s("id")).First() _
}).SelectMany(Function(a) a.Value.id.[Select](Function(h) New With { _
    h, _
    a.Key.amt, _
    a.Key.value1, _
    a.Key.value2, _
    a.Key.value3, _
    a.Key.value4, _
    Key .ConsolidatedID = a.Value.cid _
}))

答案 1 :(得分:0)

如果要填充数据表中的consolidated id列,我建议您先定义一个返回"键"的本地函数。行 - 对分组很重要的值:

Dim keyGetter = Function(row As DataRow) New With {
        Key .desc = row("desc"), 
        Key .amt = row("amt"), 
        Key .value1 = row("value 1"), 
        Key .value2 = row("value 2"), 
        Key .value3 = row("value 3"), 
        Key .value4 = row("value 4")
}

然后,对于每个组,您可以获得最大id行的count

Dim results = dt.AsEnumerable.GroupBy(keyGetter, Function(key, grp)
        Dim maxCount = grp.Max(Function(row) x("count"))
        Return grp.First(Function(row) row("count") = maxCount)
    End Function).ToDictionary(Function(x) x.Key, Function(x) x.First)

然后,您可以迭代数据表并填充列。对于每一行,使用keyGetter生成密钥,然后使用该密钥获取consolidated id

For Each row In dt.AsEnumerable
    row("consolidated id") = results(keyGetter(row))
Next