【问题标题】:Selecting from Datatable , Grouped by multiple Column with condition从数据表中选择,按条件多列分组
【发布时间】:2018-05-18 22:39:47
【问题描述】:

我有一个包含 4 个字段的数据表。

 ptime, Substation, ColumnTitle, ValueAmount

我想要具有最大 ValueAmount 的行,按 Substation 和 ColumnTitle 分组。所以假设这是我的数据表

 ptime,  Substation, ColumnTitle, ValueAmount
 --------------------------------------------
 '01:00'    'AA'       'A'          100
 '03:00'    'AA'       'A'          150
 '01:00'    'BB'       'A'          10
 '02:00'    'BB'       'A'          11
 '01:00'    'AA'       'C'          77
 '02:00'    'AA'       'C'          88
 '04:00'    'AA'       'C'          99

所以我想拥有

   ptime,  Substation, ColumnTitle, ValueAmount
 --------------------------------------------
 '03:00'    'AA'       'A'          150
 '02:00'    'BB'       'A'          11
 '04:00'    'AA'       'C'          99

为此目的最好的 linq 命令是什么? 我已经编程了:

 var newSort = from row in dtFinal.AsEnumerable()
   group row by new  {Substation = row.Field<string>("Substation"), 
            ColumnTitle= row.Field<string>("ColumnTitle")} into grp       
   select new
   {
     Substation = grp.Key.Substation,
     ColumnTitle = grp.Key.ColumnTitle,         
     ValueAmount = grp.Max(r => decimal.Parse(r.Field<string>("ValueAmount")))
   }; 

但在这种语法中,我没有 ptime 。我该怎么做。

谢谢

【问题讨论】:

  • 顺便说一句,它是Column 而不是Coulmn...
  • 执行此操作并不完全简单——首先,如果存在具有相同(最大值)值但 ptime 值不同的行,应该返回哪一个?您必须进行二次查找或加入才能找到所需的 ptime。
  • @DylanNicholson:所以没有办法只用一次查找就可以了,是吗?

标签: c# visual-studio visual-studio-2010


【解决方案1】:

您可以按此值降序对组进行排序以获得“MaxRow”,在那里您可以找到ptime

var newSort = dtFinal.AsEnumerable()
    .GroupBy(row => new
    {
        Substation = row.Field<string>("Substation"),
        ColumnTitle = row.Field<string>("ColumnTitle")
    })
    .Select(g => new
    {
        g.Key.Substation,
        g.Key.ColumnTitle,
        MaxRow = g.OrderByDescending(row => decimal.Parse(row.Field<string>("ValueAmount"))).First()
    })
    .Select(x => new 
    {
        ptime = x.MaxRow.Field<string>("ptime"), // voilà
        x.Substation,
        x.ColumnTitle,
        ValueAmount = decimal.Parse(x.MaxRow.Field<string>("ValueAmount"))
    });

由于您使用了查询语法,在这种情况下,由于let,它确实更具可读性:

var newSort = from row in dtFinal.AsEnumerable()
  let xRow = new { Row = row, valueAmount = decimal.Parse(row.Field<string>("ValueAmount")) }
  group xRow by new
  {
     Substation = row.Field<string>("Substation"),
     ColumnTitle = row.Field<string>("ColumnTitle")
  } into grp
  let maxRow = grp.OrderByDescending(x => x.valueAmount).First()
  select new
  {
     ptime = maxRow.Row.Field<string>("ptime"),
     grp.Key.Substation,
     grp.Key.ColumnTitle,
     ValueAmount = maxRow.valueAmount
  };

【讨论】:

  • 为什么需要 AsEnumerable?你知道这会生成什么 SQL 吗?
  • @DylanNicholson:DataTable 与数据库无关,LINQ 提供程序Linq-To-DataTable 实际上是Linq-To-Objects,因为DataTable 只是一个内存中的集合。所以没有生成sql。 AsEnumerable 是一种扩展方法,它允许将DataTable 视为强类型IEnumerable&lt;DataRow&gt;,即使这个旧类'Rows-property 返回一个DataRowCollection,它只实现IEnumerable 而不是IEnumerable&lt;T&gt;
  • 好吧,如果他真的意味着你是绝对正确的。但我更好奇你的技巧是否适用于数据库表。
  • @DylanNicholson:如果这是 Linq-To-Entities(例如),它仍然可以工作。我无法测试它。当然你必须删除AsEnumerable(你看到OP使用了它吗?)。
  • 我愿意,但是我看到很多 AsEnumerable 被不必要地使用的案例,或者没有真正理解在使用 EF 时从数据库中读取多少数据意味着什么。
【解决方案2】:

这可以使用以下 2 个查询来实现:

var dt = from cu in DtFinals
         group cu.ValueAmount by new
            {
                cu.Substation,
                cu.ColumnTitle,
            } into gs
            select new
            {
                Substation = gs.Key.Substation,
                ColumnTitle = gs.Key.ColumnTitle,
                ValueAmount = gs.Max()
            };

var final = from c in DtFinals
            join d in dt on 
            new {c.Substation, c.ColumnTitle,c.ValueAmount} equals 
            new {d.Substation, d.ColumnTitle, d.ValueAmount}
            select new 
            { 
                ptime = c.Ptime, 
                Substation = d.Substation, 
                ColumnTitle = d.ColumnTitle,
                ValueAmount = d.ValueAmount
            };

【讨论】:

    猜你喜欢
    • 2020-12-24
    • 2017-10-15
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    相关资源
    最近更新 更多