【问题标题】:Custom Aggregate Functions in Reports报表中的自定义聚合函数
【发布时间】:2009-10-21 15:35:24
【问题描述】:

我每天都有每个类别的生产记录,即 A 类:80 吨。每个报告行将如下所示:

             Daily                  Week to Date          Month to Date
             Actual  Plan   Var     Actual  Plan   Var    Actual   Plan   Var
Category A   100     110    -10     230      300   -70    900      1200  -300
Category B   etc. etc.

A 类:在一周的第 2 天,开采了 10 块矿石。在 10 吨/跳,这等于你在上面看到的 100 吨,在每日实际值下。因此,对于 A 类,我需要一个定义为“输入 * 10”的公式,但它并不总是一个简单的乘法因子。我需要存储输入的任何公式 - >每日数字。第 1 天,我有一个 132 吨的实际值,但已知 2 吨/天的正误差,因此本周迄今的实际值不仅仅是一个简单的总和,需要向下调整。所以我需要一个特殊的公式来计算周到日期的实际值,比如 (d1+...+dn) - 2n。

B 类:在第 2 天,化验结果显示每吨矿石含 x 公斤镍。对于 B 类,我需要镍/矿石 * 100 的每日实际公式,但同样,我必须能够将任何公式分配给 B 类的每日实际值。对于本周迄今的实际值,我是使用平均值、中位数还是模式,有调整吗?

在我的类别数据库表中,我有例如

A 类:UnitOfMeasure=Tons, DailyFormula="input*10",WeeklyFormula="(d1+...+dn) - 2n"

在计算报表中 A 类行的值时,我的代码需要应用 A 类的唯一公式。我想尝试将其用于针对原始数据的 LINQ 查询。

编辑:我需要一种方法让用户定义这些公式,并根据存储在 DB 列中的公式在运行时动态解析和评估它们。

【问题讨论】:

    标签: .net linq reporting


    【解决方案1】:

    我希望我理解正确。我对自定义分组的想法用于从类别映射到分组方法。

    为了让答案更清楚,我已经简化了一点:

    假设报表输入的行属于此类:

    public class Production
    {
        public string Category { get; private set; }
        public int DayIndex { get; private set; }
        public double Input { get; private set; }
    }
    

    在这个类中,我们有类别、当天的索引和可以表示例如开采的矿石量的输入。

    Production[] results = // The inputs to the report
    
    // The map from category to the grouping method
    var groupingMethods =
        new Dictionary<string, Func<IGrouping<string, Production>, double>>
          {
              {
                  "ore", // Category name
                  grouping =>                                        // The method
                  grouping.Sum(production => production.Input) * 10  // grouping ore 
              },                                                     // rows
              {
                  "nickel",
                  grouping =>
                  grouping.Sum(production => production.Input) - 2 * grouping.Count()
              }
          };
    
    // The query create groups based on the category
    var report = from result in results
                 group result by result.Category
                 into categoryResults
                 select new
                      {
                         // Created anonymous object with Category
                         Category = categoryResults.Key,
                         // Find the grouping method of the category, invokes it
                         // and store the result in Week column
                         Week = groupingMethods[categoryResults.Key](categoryResults)
                      };
    

    这里的主要思想是“切换”方法取决于类别。它可以很容易地更改为按其他标准进行分组,当然还可以添加和更改分组。此外,对于其他列,它可以通过为新列添加另一个字典来轻松调整。

    例如:

    var weekMethods =
        new Dictionary<string, Func<IGrouping<string, Production>, double>>() ...
    
    var monthMethods =
        new Dictionary<string, Func<IGrouping<string, Production>, int>>() ...
    
    
    from result in results
    group result by result.Category
    into categoryResults
    select new
           {
               Category = categoryResults.Key,
               Week = weekMethods[categoryResults.Key](categoryResults),
               Month = monthMethods[categoryResults.Key](categoryResults)
           };
    

    【讨论】:

    • 您完全理解,但不幸的是我忽略了一个重要因素,那就是用户应该能够定义函数并且报告代码从数据库中读取它。我想在你的帮助下,以及来自其他地方的适度的表达式解析器和表达式树,我可以做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2016-10-12
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    • 2017-08-04
    • 2016-01-30
    • 2012-01-19
    • 1970-01-01
    相关资源
    最近更新 更多