使用LINQ按time和site分组获取du最大值的DataTable行
问题:DataTable按time和site分组后获取每组du值最大的行
原始DataTable结构
dt = New DataTable() dt.Columns.AddRange(New DataColumn() { New DataColumn("time"), New DataColumn("fname", Type.GetType("System.String")), New DataColumn("note", Type.GetType("System.String")), New DataColumn("du", Type.GetType("System.Int32")), New DataColumn("site", Type.GetType("System.String"))}) dt.Rows.Add(New Object() {"2023-01-28 02:01", "aaa1", "xxx11xxxxxxx", 100, "a"}) dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb1", "xxxx22xxxxxx", 2, "b"}) dt.Rows.Add(New Object() {"2023-01-28 09:01", "ccc", "xxxx33xxxxxx", 3, "c"}) dt.Rows.Add(New Object() {"2023-01-28 02:01", "aaa2", "xxx44xxxxxxx", 3, "a"}) dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb2", "xxx55xxxxxxx", 53, "b"}) dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb3", "xxx66xxxxxxx", 89, "b"}) dt.Rows.Add(New Object() {"2023-01-28 01:01", "xxx", "xxx77xxxxxxx", 5, "x"})
当前使用的LINQ代码(不符合预期)
Dim MYquery = (From p In dt.Select() Group p By ID = New With _ {Key .time = p("time").ToString.Trim, _ Key .site = p("site")} _ Into Group Select Group(0)).ToArray.CopyToDataTable
期望结果
| time | fname | note | du | site |
|---|---|---|---|---|
| 2023-01-28 02:01 | aaa1 | xxx11xxxxxxx | 100 | a |
| 2023-01-28 03:01 | bbb3 | xxx66xxxxxxx | 89 | b |
| 2023-01-28 09:01 | ccc | xxxx33xxxxxx | 3 | c |
| 2023-01-28 01:01 | xxx | xxx77xxxxxxx | 5 | x |
解决方案
你当前的代码只是取了每组的第一行,没有按照du值筛选最大值对应的行。需要修改分组后的逻辑,对每组内的行按du降序排序后取第一行,或者直接使用MaxBy方法获取du最大的行。
修改后的代码(方法一:排序取首行,兼容所有.NET版本)
Dim MYquery = (From p In dt.AsEnumerable() Group p By ID = New With { Key .time = p.Field(Of String)("time").Trim(), Key .site = p.Field(Of String)("site") } Into Group Select Group.OrderByDescending(Function(row) row.Field(Of Integer)("du")).First()).CopyToDataTable()
修改后的代码(方法二:使用MaxBy,需.NET 6+支持)
Dim MYquery = (From p In dt.AsEnumerable() Group p By ID = New With { Key .time = p.Field(Of String)("time").Trim(), Key .site = p.Field(Of String)("site") } Into Group Select Group.MaxBy(Function(row) row.Field(Of Integer)("du"))).CopyToDataTable()
代码说明
- 用
dt.AsEnumerable()替代dt.Select(),更符合LINQ操作DataTable的规范,同时通过强类型的Field<T>方法避免类型转换错误。 - 分组后,对每组的行通过
OrderByDescending(Function(row) row.Field(Of Integer)("du"))按du降序排序,再取第一行,即可得到该组du值最大的行。 - 如果使用.NET 6及以上版本,
MaxBy方法可以直接获取集合中指定属性最大的元素,代码更简洁高效。
内容的提问来源于stack exchange,提问作者marana ford
相关产品推荐
相关产品推荐

