C# LINQ GroupBy,从计数中查找最大值(然后是一些…)

C# LINQ GroupBy,从计数中查找最大值(然后是一些…),c#,linq,C#,Linq,我一直想弄明白这件事有一段时间了 我正在尝试查询我公司的许可证使用情况。我有一个捕获数据的服务和一个存储数据的SQL server DB。我的问题是查询数据。我认为这是最简单的部分,但不是那么简单 每五分钟捕获一次数据,并记录捕获时间 最大值需要在特定的捕获点,但在特定的时间范围内(60分钟) 数据需要按特定字段分组 用户可以选择应用程序、功能和/或部门,以及查询的开始和结束时间 样本数据 +-------------+---------+----------+-----------------

我一直想弄明白这件事有一段时间了

我正在尝试查询我公司的许可证使用情况。我有一个捕获数据的服务和一个存储数据的SQL server DB。我的问题是查询数据。我认为这是最简单的部分,但不是那么简单

  • 每五分钟捕获一次数据,并记录捕获时间
  • 最大值需要在特定的捕获点,但在特定的时间范围内(60分钟)
  • 数据需要按特定字段分组
  • 用户可以选择应用程序、功能和/或部门,以及查询的开始和结束时间
  • 样本数据

    +-------------+---------+----------+------------------+
    | Application | Feature | Division |   RecordedTime   |
    +-------------+---------+----------+------------------+
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:05 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:05 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:05 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:10 |
    +-------------+---------+----------+------------------+
    
    结果应该是

    Time: 2014-01-01 00:00
    +------+-------+------+---+
    | App1 | Feat1 | Div1 | 4 |
    | App1 | Feat1 | Div2 | 2 |
    | App1 | Feat2 | Div2 | 1 |
    +------+-------+------+---+
    
    以下是我到目前为止的代码:(一些是从其他关于堆栈溢出的帖子中拼凑而来的)

    var results=context.ViewData
    其中(x=>(x.FeatureID==1)和
    StartTimeInput=x.RecordedDateTime)
    .GroupBy(x=>new
    {
    Application=x.ApplicationName,
    Feature=x.FeatureName,
    除法,除法,
    RecordedDateTime=x.RecordedDateTime
    })
    .选择(x=>new
    {
    应用程序=x.Key.Application,
    Feature=x.Key.Feature,
    除法=x.Key.Division,
    RecordedDateTime=x.Key.RecordedDateTime,
    Count=x.Count()
    })
    .OrderBy(x=>x.RecordedDateTime)
    .AsEnumerable().GroupBy(x=>
    {
    var stamp=x.RecordedDateTime;
    stamp=stamp.AddMinutes(-(stamp.Minute%60));
    返回印章;
    }).选择(x=>new
    {
    邮票=x.钥匙,
    数据=x。选择(y=>new
    {
    应用=y。应用,
    特征=y。特征,
    除法,
    计数=y。计数
    })
    });
    
    上面的代码让我更接近,但它没有按应用程序、功能和分区为我提供每小时的最大值

    使现代化 为了澄清这一点,我遇到的麻烦是按组查找特定时间点上60分钟范围内计数的最大值

    根据样本数据上记录的时间、应用程序、功能、分区进行分组,将得到以下结果:

    +------+-------+------+---+------------------+
    | App1 | Feat1 | Div1 | 4 | 2014-01-01 00:00 |
    | App1 | Feat1 | Div2 | 1 | 2014-01-01 00:00 |
    | App1 | Feat1 | Div1 | 1 | 2014-01-01 00:05 |
    | App1 | Feat1 | Div2 | 2 | 2014-01-01 00:05 |
    | App1 | Feat2 | Div2 | 1 | 2014-01-01 00:10 |
    +------+-------+------+---+------------------+
    
    Between the time range 2014-01-01 00:00 and 2014-01-01 01:00, 
    the marked lines should be selected as the maximum value for that time range 
    if you assume that between that time range, none of the grouping exceed that value:
    
       +------+-------+------+---+------------------+
    -->| App1 | Feat1 | Div1 | 4 | 2014-01-01 00:00 |<--
       | App1 | Feat1 | Div2 | 1 | 2014-01-01 00:00 |
       | App1 | Feat1 | Div1 | 1 | 2014-01-01 00:05 |
    -->| App1 | Feat1 | Div2 | 2 | 2014-01-01 00:05 |<--
    -->| App1 | Feat2 | Div2 | 1 | 2014-01-01 00:10 |<--
       +------+-------+------+---+------------------+
    
    +------+-------+------+---+------------------+
    |附件1-壮举1-分区1-分区4-2014-01-01 00:00|
    |附件一:壮举二部2014-01-01 00:00|
    |附件一:壮举1第1分部2014-01-01 00:05|
    |附件一:壮举二部2014-01-01 00:05|
    |附件一:壮举二部一2014-01-01 00:10|
    +------+-------+------+---+------------------+
    在时间范围2014-01-01 00:00和2014-01-01:00之间,
    应选择标记行作为该时间范围的最大值
    如果您假定在该时间范围内,所有分组都不会超过该值:
    +------+-------+------+---+------------------+
    
    -->|1月1日1244\1244\1244124412441244\1244124412411244124112411241124112441241124112411241124112411244124412441244\1244\1244\12411244\1241 124112411241\1241\12411241\12411244;;;;;;;;;该该政政政政政政政政政政政政政政政政政政政政政政政政政政政政1 1241 1241 1241 1241 1241 1241 1241 1241 App1 | Feat2 | Div2 | 5 | 2014-01-01 00:40 |您可以在单个查询中完成此操作。如果您喜欢方法语法,请告诉我,我可以为您翻译

    var query =   from x in context.ViewData
                  where x.FeatureID == 1
                  where StartTimeInput <= x.RecordedDateTime
                  where EndTimeInput >= x.RecordedDateTime
                  group x by new { x.ApplicationName, x.FeatureName, x.Division } into x
                  select new
                  {
                    Application = x.Key.ApplicationName,
                    Feature = x.Key.FeatureName,
                    Division = x.Key.Division,
                    Max = (from g in x
                          group g by g.RecordedDateTime into g
                          orderby g.Count() descending
                          select g.Count()).FirstOrDefault()
                  };
    

    我认为你的例子是错误的…你有9行,但你的结果集只有7(4+2+1)@Aducci-我在寻找最大值,而不是总和。按应用程序、功能和划分第一组。然后按记录的日期对这些数据进行分组。按计数降序排列子组,然后取第一个。不清楚你在问什么。首先,定义什么是最大值。第二,若你们所说的最大值是指计数,那个么“App1,Feat1,Div1”应用程序每小时的最大值是5,而不是4(60分钟规则)?
    +-------------+---------+----------+------------------+
    | Application | Feature | Division |   RecordedTime   |
    +-------------+---------+----------+------------------+
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:00 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:05 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:05 |
    | App1        | Feat1   | Div2     | 2014-01-01 00:05 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:10 |
    .......................................................
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat1   | Div1     | 2014-01-01 00:40 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:40 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:40 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:40 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:40 |
    | App1        | Feat2   | Div2     | 2014-01-01 00:40 |
    +-------------+---------+----------+------------------+
    
    The grouping and results would look like this:
    
       +------+-------+------+---+------------------+
       | App1 | Feat1 | Div1 | 4 | 2014-01-01 00:00 |
       | App1 | Feat1 | Div2 | 1 | 2014-01-01 00:00 |
       | App1 | Feat1 | Div1 | 1 | 2014-01-01 00:05 |
       | App1 | Feat1 | Div2 | 2 | 2014-01-01 00:05 |
    -->| App1 | Feat2 | Div2 | 1 | 2014-01-01 00:10 |<--
    -->| App1 | Feat1 | Div1 | 7 | 2014-01-01 00:40 |<--
    -->| App1 | Feat2 | Div2 | 5 | 2014-01-01 00:40 |<--
       +------+-------+------+---+------------------+
    
    var query =   from x in context.ViewData
                  where x.FeatureID == 1
                  where StartTimeInput <= x.RecordedDateTime
                  where EndTimeInput >= x.RecordedDateTime
                  group x by new { x.ApplicationName, x.FeatureName, x.Division } into x
                  select new
                  {
                    Application = x.Key.ApplicationName,
                    Feature = x.Key.FeatureName,
                    Division = x.Key.Division,
                    Max = (from g in x
                          group g by g.RecordedDateTime into g
                          orderby g.Count() descending
                          select g.Count()).FirstOrDefault()
                  };
    
    ...
    let max = (from g in x
               group g by g.RecordedDateTime into g
               orderby g.Count() descending
               select g).FirstOrDefault()
    select new
    {
      ...
      Max = max.Count(),
      DateTime = max.Key
    };