简体   繁体   English

使用LINQ to Entities的外连接查询

[英]Outer join query using LINQ to Entities

There are 0 to n departments in my company, 0 to n offices in 1 department, and 0 to n emplyees in 1 office.Now I need a query using linq to list emplyees's average age by department, if nobody in a department then default average is 0. code is below: 我公司有0到n个部门,1个部门有0到n个办公室,1个办公室有0到n个工作人员。现在我需要使用linq查询按部门列出员工的平均年龄,如果部门中没有人则默认平均是0.代码如下:

    DataContext ctx = new DataContext();

    var q0 = from d in ctx.Departments
             join o in ctx.Offices on d.Id equals o.DepartmentId
             join e in ctx.Employees on o.Id equals e.OfficeId
             group e by d into de
             select new {
                DepartmentId = de.Key.Id,
                AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
             };


    var q1 = from d in ctx.Departments
             join de in q0 on d.Id equals de.DepartmentId into des
             from de in des.DefaultIfEmpty()
             select new
             {
                 DepartmentName = d.Name,
                 AverageAge = de == null ? 0 : de.AverageAge
             };

    var result = q1.ToList();
    foreach (var item in result)
    {
        Console.WriteLine("{0}-{1}", item.DepartmentName, item.AverageAge);
    }
    ctx.Dispose();

But how to combine q0 and q1 to one query? 但是如何将q0和q1组合成一个查询呢?

    were you meaning something along the lines of:

var newQ2 = from d in ctx.Departments
                 outer left join o in ctx.Offices on d.Id equals o.DepartmentId
                 outer left join e in ctx.Employees on o.Id equals e.OfficeId
                 group e by d into de
                 select new {
                    DepartmentId = de.Key.Id,
                    AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
                 };

changed to: 变成:

var newQ2 = from d in ctx.Departments
                     join o in ctx.Offices on d.Id equals o.DepartmentId
                     join e in ctx.Employees on o.Id equals e.OfficeId
                     group e by d into de.DefaultIfEmpty()
                     select new {
                        DepartmentId = de.Key.Id,
                        DepartdentName = select d.Name from d where d.id = de.Key.Id,
                        AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
                     };

Addendum: I would use a sub-select to match up the extra name, not knowing your db layout I have improvised from your code, but you could make it more efficient and have a multipart join based on sub-selects as well. 附录:我会使用一个子选项来匹配额外的名称,不知道我从你的代码中即兴创建的数据库布局,但你可以使它更高效,并且还有基于子选择的多部分连接。 Sorry I cant test this code out at work, I can approximate fairly well, but would need some more info on where your department names are located if you need a more detailed answer:) I have changed the outer left joins back to joins, sorry I forgot in c# with linq you can use DefaultIfEmpty() to cause outer left join behaviour in code. 对不起,我不能在工作中测试这个代码,我可以很好地估计,但如果你需要更详细的答案,需要更多关于你的部门名称所在位置的信息:)我已经将左外连接更改回连接,抱歉我忘记在c#中使用linq你可以使用DefaultIfEmpty()在代码中引起外部左连接行为。

An outer left join will return nulls where there are no corresponding values, but will allow returns on any parts that do have a corresponding value. 外部左连接将返回没有相应值的空值,但允许返回具有相应值的任何部分。 Join however will not return any null entries which I suspect is why you had the two queries? 然而,加入不会返回任何空条目,我怀疑这是为什么你有两个查询?

The only caveat on the query I have presented is that you will need to infill any values you require before you use them if they are nulls, for example DepartmentId will need some logic to populate it in case DE is null. 我提出的查询的唯一警告是,如果它们是空值,您将需要在使用之前填充所需的任何值,例如,如果DE为null,则DepartmentId将需要一些逻辑来填充它。

Thank you all,I have got the answer: 谢谢大家,我得到了答案:

        var q1 = 
                 from d in ctx.Departments 
                 from o in ctx.Offices.Where(o => o.DepartmentId == d.Id).DefaultIfEmpty()
                 from e in ctx.Employees.Where(e =>  e.OfficeId == o.Id).DefaultIfEmpty()
                 group e by d into de
                 select new {
                    DepartmentName = de.Key.Name,
                    AverageAge = de.Average(e => e == null ? 0 : e.Age),
                 };

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

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