LINQ join,group by,sum

时间:2017-02-06 23:22:07

标签: c# linq join group-by sum

我正在创建一个安全跟踪HR应用程序,我正在尝试使用LINQ来返回每个安全事件类型的每个月的丢失小时数。相关的实体/表格列是:

[safety_incident]:
    [incident_id]
    [incident_date]
    [incident_type]
    [facility_id]

[safety_hours]:
    [safety_hours_id]
    [incident_id]
    [safety_hours_date]
    [lost_hours] 

safety_incident和safety_hours之间的关系是0..n,其中safe_hours注意到特定日期的事件丢失了几个小时。我试图为事件类型和月份的每个组合返回一个记录/对象,超过一年(不一定都在同一日历年),其中丢失的小时数大于0.没有一年的边界或限制在设施上,我从SQL得到了我需要的东西:

SELECT (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)),
    inc.incident_type, sum(sh.lost_hours)
FROM [hr].[safety_hours] sh
INNER JOIN [hr].safety_incident inc ON sh.incident_id = inc.incident_id
GROUP BY (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)),
    inc.incident_type
HAVING sum(sh.lost_hours) > 0
ORDER BY (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)),
    inc.incident_type

我最接近已接受的LINQ查询是:

var monthInjuryHours =
                from sh in _context.safety_hours
                where sh.safety_hours_date >= firstMonth && sh.safety_hours_date < monthAfterLast && sh.lost_hours > 0
                join inc in _context.safety_incident on sh.incident_id equals (inc.incident_id) into most
                from m in most
                where (facID == 0 || m.facility_id == facID)
                group m by new
                {
                    m.incident_type,
                    month = new DateTime(sh.safety_hours_date.Year, sh.safety_hours_date.Month, 1)
                } into g
                select new
                {
                    injury = g.Key.incident_type,
                    month = g.Key.month,
                    hours = g.Sum(h => h.lost_hours)    // ERROR, can't access lost_hours
                };

不幸的是,我无法在“小时”行中指定lost_hours,或者在safe_hours的任何属性中,只有“_”之后才会出现safety_incident的属性。非常感谢任何帮助,谢谢...

编辑:我能够重新排列查询以切换两个表的顺序并得到一些运行的东西:

    var monthInjuryHours =
        from inc in _context.safety_incident
        where (facID == 0 || inc.facility_id == facID) && inc.incident_date < monthAfterLast
        join sh in _context.safety_hours on inc.incident_id equals (sh.incident_id) into most
        from m in most
        where m.safety_hours_date >= firstMonth && m.safety_hours_date < monthAfterLast
            && m.lost_hours > 0
        group m by new
        {
            // Note new aliases
            inc.incident_type,
            month = new DateTime(m.safety_hours_date.Year, m.safety_hours_date.Month, 1)
        } into g
        select new
        {
            injury = g.Key.incident_type,
            month = g.Key.month,
            hours = g.Sum(h => h.lost_hours)
        };

但是当我尝试使用foreach迭代它时,指向“in”关键字的NotSupportedException告诉我“在LINQ to Entities中只支持无参数构造函数和初始值设定项”。我发誓我已经有其他查询返回了匿名类型的集合,但无论如何......

1 个答案:

答案 0 :(得分:0)

嗯,现在,答案是&#34; F(orget)LINQ&#34;。感谢Yuckthis topic的鼓舞人心的回答,Where()之后的ToList()允许此语法准确获取我之后的结果:

var monthInjuryHours = _context.safety_incident.Join(_context.safety_hours,
    inc => inc.incident_id, sh => sh.incident_id, (inc, sh) => new { Inc = inc, Hours = sh })
    .Where(j => j.Hours.lost_hours > 0 && (facID == 0 || j.Inc.facility_id == facID)
                && j.Inc.incident_date < monthAfterLast
                && j.Hours.safety_hours_date >= firstMonth
                && j.Hours.safety_hours_date < monthAfterLast).ToList()    //Fixes things
    .GroupBy(x => new { Month = new DateTime(x.Hours.safety_hours_date.Year,
                           x.Hours.safety_hours_date.Month, 1), x.Inc.incident_type })
    .Select(g => new { g.Key.Month, g.Key.incident_type,
                       LostHours = g.Sum(x => x.Hours.lost_hours) })
    .OrderBy(h => h.Month).ThenBy(h => h.incident_type);

我知道这不是最漂亮或最简单的例子,但我希望它有助于某人。