繁体   English   中英

LINQ join,group by,sum

[英]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,或者安全_hours的任何属性,只有在“h”之后才会出现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中只支持无参数构造函数和初始值设定项”。 我发誓我有其他查询返回匿名类型的集合,但无论如何......

好吧,现在,答案是“F(orget)LINQ”。 感谢Yuck这个主题的鼓舞人心的回答,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);

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM