Linq查询查找每组的平均时差

时间:2017-09-06 15:27:01

标签: c# linq

我有一个数据表,我想查询以获得每组案例ID的平均时差。我的数据如下所示。

 Name     Case ID    Incept Time                  Edit Time
 ---------------------------------------------------------------------------
 Blue        1       2017-02-26T02:35:49-04:00    2017-03-26T02:35:49-04:00
 Blue        1       2017-02-26T02:34:49-04:00    2017-04-26T02:35:49-04:00
 Blue        1       2017-02-26T02:33:49-04:00    2017-05-26T02:35:49-04:00
 Blue        2       2017-02-26T02:32:49-04:00    2017-06-26T02:35:49-04:00
 Blue        2       2017-02-26T02:31:49-04:00    2017-07-26T01:35:49-04:00
 Blue        2       2017-02-26T02:30:49-04:00    2017-08-26T03:35:49-04:00
 Red         5       2017-02-26T02:25:49-04:00    2017-09-26T04:35:49-04:00
 Red         5       2017-02-26T02:15:49-04:00    2017-10-26T05:35:49-04:00
 Red         1       2017-02-26T02:05:49-04:00    2017-11-26T02635:49-04:00
 Red         1       2017-02-26T01:35:49-04:00    2017-12-26T02:35:49-04:00
 Red         5       2017-02-26T05:35:49-04:00    2017-12-27T02:35:49-04:00

到目前为止,我有以下查询可以进入每组Case ID并获取最小值和最大值。

private IEnumerable<DataRow> _data;

var query = 
    from data in this._data
    group data by data.Field<string>("Name") into groups
    select new
    {
        formName = groups.Key,

        caseDiffs = 
            from d in groups
            group d by d.Field<string>("Case ID") into grps
            select new
            {
                min = grps.Min(t => 
                    DateTimeOffset.ParseExact(t.Field<string>("Incept Time"), "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)
                ),
                max = grps.Max(t => 
                    DateTimeOffset.ParseExact(t.Field<string>("Edit Time"), "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)
                )
            }
    };

我的问题是

1)是否可以在查询中包含最小值和最大值(每个案例ID组)之间的差异

2)最后,如何计算平均值,如下图所示

enter image description here

2 个答案:

答案 0 :(得分:1)

更新以反映您更改的问题...

我已将此分为三个单独的查询,以便您可以更轻松地阅读(如果需要,可以合并):

        //convert the data using a projection query
        var query1 = from data in _data
                     let inceptTime = DateTimeOffset.ParseExact(data.Field<string>("Incept Time"), "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)
                     let editTime = DateTimeOffset.ParseExact(data.Field<string>("Edit Time"), "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)
                     let difference = editTime - inceptTime
                     select new
                     {
                         name = data.Field<string>("Name"),
                         caseId = data.Field<string>("Case ID"),
                         inceptTime,
                         editTime,
                         difference
                     };

        //group by caseID (also by NAME, but that won't matter for this grouping and is needed in query3)
        var query2 = from data in query1
                     group data by new { data.caseId, data.name } into groups
                     let min = groups.Min(x => x.inceptTime)
                     let max = groups.Max(x => x.editTime)
                     select new
                     {
                         name = groups.Key.name,
                         caseId = groups.Key.caseId,
                         min,
                         max,
                         diff = max - min
                     };

        //now group by name
        var query3 = from data in query2
                     group data by new { data.name } into groups
                     select new
                     {
                         name = groups.Key.name,
                         minDiff = groups.Min(x => x.diff),
                         maxDiff = groups.Max(x => x.diff),
                         avgDiff = new TimeSpan((long)groups.Average(x => x.diff.Ticks)),
                     };

注意:&#34;编辑时间&#34;第9条记录的格式无效

答案 1 :(得分:1)

您只需要在LINQ查询中定义一些let变量。事实上,大约还有3条线路。您的分组LINQ应如下所示:

var query = 
    from data in this._data
    group data by data.Field<string>("Name") into groups
    select new
    {
        formName = groups.Key,

        caseDiffs = from d in groups group d by d.Field<string>("Case ID") into grps

        // three variables here, so that you can do the 
        // date math that you require!
        let minDt = caseGroup.Min(t => 
                DateTimeOffset.ParseExact(t.Field<string>("Incept Time"), 
                "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)

        let maxDt = grps.Max(t => 
                DateTimeOffset.ParseExact(t.Field<string>("Edit Time"), 
                "yyyy-MM-ddTHH:mm:sszzzz", CultureInfo.InvariantCulture)

        let diffInSecs = (maxDt - minDt).TotalSeconds

        select new
        {
            min = minDt,
            max = maxDt,
            diff = diffInSecs
        }
    };

希望有所帮助!