LINQ Left Join And Right Join
我需要帮助,
我有两个名为a和b的数据表,我需要a的所有行和b的匹配行
前任:
1 2 3 4 5 6 | A: B: User | age| Data ID | age|Growth 1 |2 |43.5 1 |2 |46.5 2 |3 |44.5 1 |5 |49.5 3 |4 |45.6 1 |6 |48.5 |
我需要输出:
1 2 3 4 5 | User | age| Data |Growth ------------------------ 1 |2 |43.5 |46.5 2 |3 |44.5 | 3 |4 |45.6 | |
您提供的示例数据和输出并不演示左联接。如果是左连接,您的输出将如下所示(请注意,对于用户1,我们有3个结果,即,对于用户1拥有的每个增长记录,我们有一个结果):
1 2 3 4 5 6 7 | User | age| Data |Growth ------------------------ 1 |2 |43.5 |46.5 1 |2 |43.5 |49.5 1 |2 |43.5 |48.5 2 |3 |44.5 | 3 |4 |45.6 | |
假设您仍然需要一个左联接;下面介绍如何在LINQ中执行左联接:
1 2 3 4 5 6 7 8 9 | var results = from data in userData join growth in userGrowth on data.User equals growth.User into joined from j in joined.DefaultIfEmpty() select new { UserData = data, UserGrowth = j }; |
如果要进行正确的联接,只需交换要从上方选择的表,如下所示:
1 2 3 4 5 6 7 8 9 | var results = from growth in userGrowth join data in userData on growth.User equals data.User into joined from j in joined.DefaultIfEmpty() select new { UserData = j, UserGrowth = growth }; |
代码的重要部分是into语句,后面是defaultifempty。这告诉Linq,如果另一个表中没有匹配的结果,我们希望有默认值(即空值)。
琼斯医生显示左外联接,但正确的答案会略有不同-因为在最初的问题中,两个表在年龄字段上链接,以便根据需要获得准确的结果,应使用以下代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | .... //ctx = dataContext class - not shown here. var user1 = new UserData() { User = 1, Age = 2, Data = 43.5 }; var user2 = new UserData() { User = 2, Age = 3, Data = 44.5 }; var user3 = new UserData() { User = 3, Age = 4, Data = 45.6 }; ctx.UserData.AddRange(new List<UserData> { user1, user2, user3 }); var growth1 = new UserGrowth() { Id = 1, Age = 2, Growth = 46.5 }; var growth2 = new UserGrowth() { Id = 1, Age = 5, Growth = 49.5 }; var growth3 = new UserGrowth() { Id = 1, Age = 6, Growth = 48.5 }; ctx.UserGrowth.AddRange(new List<UserGrowth> { growth1, growth2, growth3 }); var query = from userData in ctx.UserData join userGrowth in ctx.UserGrowth on userData.Age equals userGrowth.Age into joinGroup from gr in joinGroup.DefaultIfEmpty() select new { User = userData.User, age = userData.Age, Data = (double?)userData.Data, Growth = (double?)gr.Growth }; Console.WriteLine("{0} | {1} | {2} | {3}","User","age","Data","Growth"); foreach (var x in query) { Console.WriteLine("{0} | {1} | {2} | {3}", x.User, x.age, x.Data, x.Growth); } .... with following entity classes: public class UserData { [Key] public int User { get; set; } public int Age { get; set; } public double Data { get; set; } } public class UserGrowth { public int Id { get; set; } public int Age { get; set; } public double Growth { get; set; } } |
简单实例
模型
1 2 3 4 5 6 7 8 9 10 11 12 | class Employee { public string Name { get; set; } public int ID { get; set; } public int ProjectID { get; set; } } class Project { public int ProjectID { get; set; } public string ProjectName { get; set; } } |
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public void leftrighjoin(){ Project P1 = new Project() { ProjectID = 1, ProjectName ="UID" }; Project P2 = new Project() { ProjectID = 2, ProjectName ="RBS" }; Project P3 = new Project() { ProjectID = 3, ProjectName ="XYZ" }; // Employee List List<Employee> ListOfEmployees = new List<Employee>(); ListOfEmployees.AddRange((new Employee[] { new Employee() { ID = 1, Name ="Sunil", ProjectID = 1 }, new Employee() { ID = 1, Name ="Anil", ProjectID = 1 }, new Employee() { ID = 1, Name ="Suman", ProjectID = 2 }, new Employee() { ID = 1, Name ="Ajay", ProjectID = 3 }, new Employee() { ID = 1, Name ="Jimmy", ProjectID = 4 }})); //Project List List<Project> ListOfProject = new List<Project>(); ListOfProject.AddRange(new Project[] { P1, P2, P3 }); //Left join var Ljoin = from emp in ListOfEmployees join proj in ListOfProject on emp.ProjectID equals proj.ProjectID into JoinedEmpDept from proj in JoinedEmpDept.DefaultIfEmpty() select new { EmployeeName = emp.Name, ProjectName = proj != null ? proj.ProjectName : null }; //Right outer join var RJoin = from proj in ListOfProject join employee in ListOfEmployees on proj.ProjectID equals employee.ProjectID into joinDeptEmp from employee in joinDeptEmp.DefaultIfEmpty() select new { EmployeeName = employee != null ? employee.Name : null, ProjectName = proj.ProjectName }; //Printing result of left join Console.WriteLine(string.Join(" ", Ljoin.Select(emp =>" Employee Name =" + emp.EmployeeName +", Project Name =" + emp.ProjectName).ToArray<string>())); //printing result of right outer join Console.WriteLine(string.Join(" ", RJoin.Select(emp =>" Employee Name =" + emp.EmployeeName +", Project Name =" + emp.ProjectName).ToArray<string>())); } |
简单的方法是使用let关键字。这对我有用。
1 2 3 4 5 6 7 8 9 | from AItem in Db.A Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault() Where SomeCondition Select new YourViewModel { X1 = AItem.a, X2 = AItem.b, X3 = BItem.c } |
这是对左连接的模拟。如果B表中的每个项与某个项不匹配,则b item返回空值