【问题标题】:Datatable: add computed column with subtotals数据表:添加带有小计的计算列
【发布时间】:2014-08-21 09:46:01
【问题描述】:

我通过查询大型 mysql 数据库生成了一个数据表。 这导致了大约 7000 行。现在我想添加一个列,计算列“BREAK2”中每个唯一值的“QUANTITY”列的总和(如“分组依据”)。

例子:

BREAK2 | QUANTITY | COMPUTED

A          10         30
B          20         40
A          10         30
A          20         30
B          20         40

如果我使用

Dim dc As DataColumn = New DataColumn
dc.DataType = System.Type.GetType("System.Double")
dc.ColumnName = "SumQTY"
dt.Columns.Add(dc)

For Each dr As DataRow In DT.Rows
    dr("SumQTY") = DT.Compute("Sum(QUANTITY)", "BREAK2 = '" & dr("BREAK2") & "'")
Next

这需要很长时间(在我中断之前几分钟)。

当我使用名为 BRIO 的查询工具查询相同的数据,并使用公式“Sum(QUANTITY,BREAK2)”添加计算列时,大约需要 1 秒才能得到结果。

这些方法之间可能有什么区别?
为什么 VB.net 代码需要这么长时间? 我曾尝试使用 LINQ,但性能同样不佳。

谢谢。 纳斯

【问题讨论】:

  • 只是一个提示:如果你有 2000 行的列 BREAK2='A' 你调用 Compute 2000 次以获得相同的结果。
  • 您应该只使用 SQL 来获取该数据。如果您愿意,您可以使用聚合值生成一个结果集,然后将其加入您已有的结果集。

标签: vb.net datatable


【解决方案1】:

这似乎相当快

Sub Main
    Dim sw = new Stopwatch()
    sw.Start()
    Dim rnd = new Random()
    Dim dt = new DataTable()
    dt.Columns.Add("BREAK2", "".GetType())
    dt.Columns.Add("QUANTITY", 0.GetType())
    dt.Columns.Add("COMPUTED", 0.GetType())
    for i = 0 to 7000
        dt.Rows.Add("A", rnd.Next(0, 30))
        dt.Rows.Add("B", rnd.Next(0, 30))
        dt.Rows.Add("C", rnd.Next(0, 30))
        dt.Rows.Add("D", rnd.Next(0, 30))
    Next

    Dim keys As List(Of String) = dt.AsEnumerable() _ 
                                  .Select(Function(x) x("BREAK2").ToString()) _ 
                                  .Distinct().ToList()
    For Each k in keys
        Dim listOfRow = dt.AsEnumerable() _ 
                        .Where(Function(x) x.Field(Of String)("BREAK2") = k).ToList()

        Dim total = listOfRow.Sum(Function(t) t.Field(Of Integer)("QUANTITY"))
        For Each row in listOfRow
           row.SetField(Of Integer)("COMPUTED", total)
        Next
    Next
    sw.Stop()
    Console.WriteLine(sw.ElapsedMilliseconds)
End Sub

正如我在上面的评论中所说,重新计算相同的值数千次是愚蠢的。
使用 LINQ,您可以提取 BREAK2 列的唯一值,只对键标识的行子集执行一次求和,然后将相同的行子集设置为总数。
在我的 PC 上,这最多需要 100 毫秒。

【讨论】:

  • 感谢您的快速回复。在我的示例中,“BREAK2”列似乎只有 2 个可能的值,但更像是总共 7000 行中的 BREAK2 有 6000 个不同的值。抱歉,如果我提供了误导性信息。我试过你的代码,它现在已经运行了 2 分钟..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 2023-03-15
  • 2017-11-27
  • 1970-01-01
  • 2021-04-18
相关资源
最近更新 更多