多表查询Ⅰ
在学习之前,我们要做一些准备工作,我们需要创建User对象和包含User对象的集合,创建Salary对象和包含Salary对象的集合,作为后面查询和输出的数据源,参见这篇文章C#进阶之LINQ表达式总结完成准备工作。
数据源1:
数据源2:
1、交集 Intersect
如同数学中中的交集,集合[1,2,3]和集合[2,3,4]的交集是[2,3],Linq的交集是两种相同结果类型结果集的重合部分。
比如下面这个例子:
/* SQL里的表达: 求25岁以上且薪水超过17000的用户姓名、职业*/SELECTname,occupationFROMUserWHEREage>25; /*先查询25岁以上的用户姓名、职业*/INTERSECTSELECTname,occupationFROMSalaryWHEREsalary>17000; /*再查询薪水超过17000的用户姓名、职业*/
/* 在比较两个对象元素之前,我们先重写一个比较对象*/classCompareUser : IEqualityComparer<User>{ publicboolEquals(Userx, Usery) { if (x.name==y.name&&x.occupation.ToLower() ==y.occupation.ToLower()) returntrue; returnfalse; } publicintGetHashCode(Userobj) { return (obj.name+obj.occupation).Length; } } /*查询年龄大于25的用户集合,投影存储他们的姓名和职业*/List<User>user_list=list.Where(u=>u.age>25) .Select(g=>newUser(){ name=g.name, occupation=g.occupation }).ToList(); /*查询薪水大于17000的用户集合,投影存储他们的姓名和职业*/List<User>salary_list=salaryList.Where(u=>u.salary>17000) .Select(g=>newUser(){ name=g.name, occupation=g.occupation }).ToList(); /*取上面两个集合的交集为结果集*/List<User>result_list=user_list.Intersect(salary_list, newCompareUser()).ToList();
/* 遍历 输出 */foreach (Useruserinuser_list) { Console.WriteLine(PrintUserObject(user)); } foreach (Useruserinsalary_list) { Console.WriteLine(PrintUserObject(user)); } foreach (Useruserinresult_list) { Console.WriteLine(PrintUserObject(user)); } /* 输出结果 *//* 年龄大于25的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher} {id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher} {id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor} {id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor} {id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor} {id=0, name=JiangLong, age=0, gender=False, occupation=Builder} /* 薪水高于17000的用户集合 */{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor} /* 交集结果集 */{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}
2、并集 Union
如同数学中中的并集,集合[1,2,3]和集合[2,3,4]的交集是[1,2,3,4],Linq的并集是两种相同结果类型结果集的合并集合。
比如下面这个例子:
/* SQL里的表达: 求25岁以上和薪水少于8000的用户姓名、职业*/SELECTname,occupationFROMUserWHEREage>25; /*先查询25岁以上的用户姓名、职业*/UNIONSELECTname,occupationFROMSalaryWHEREsalary<8000; /*再查询薪水少于8000的用户姓名、职业*/
/*同样需要上面求交集时的比较对象*//*查询年龄大于25的用户集合,投影存储他们的姓名和职业*/List<User>user_list=list.Where(u=>u.age>25) .Select(g=>newUser(){ name=g.name, occupation=g.occupation }).ToList(); /*查询薪水少于8000的用户集合,投影存储他们的姓名和职业*/List<User>salary_list=salaryList.Where(u=>u.salary<8000) .Select(g=>newUser(){ name=g.name, occupation=g.occupation }).ToList(); /*取上面两个集合的交集为结果集*/List<User>result_list=user_list.Union(salary_list, newCompareUser()).ToList();
/* 遍历 输出 */foreach (Useruserinuser_list) { Console.WriteLine(PrintUserObject(user)); } foreach (Useruserinsalary_list) { Console.WriteLine(PrintUserObject(user)); } foreach (Useruserinresult_list) { Console.WriteLine(PrintUserObject(user)); } /* 输出结果 *//* 年龄大于25的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher} {id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher} {id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor} {id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor} {id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor} {id=0, name=JiangLong, age=0, gender=False, occupation=Builder} /* 薪水少于8000的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher} {id=0, name=ZhangJin, age=0, gender=False, occupation=Student} {id=0, name=LiuJin, age=0, gender=False, occupation=Builder} {id=0, name=HuZiming, age=0, gender=False, occupation=Student} {id=0, name=HuJin, age=0, gender=False, occupation=Student} /* 并集结果集 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher} {id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher} {id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor} {id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor} {id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor} {id=0, name=JiangLong, age=0, gender=False, occupation=Builder} {id=0, name=ZhangJin, age=0, gender=False, occupation=Student} {id=0, name=LiuJin, age=0, gender=False, occupation=Builder} {id=0, name=HuZiming, age=0, gender=False, occupation=Student} {id=0, name=HuJin, age=0, gender=False, occupation=Student}
3、全集 Concat
不同于并集(Union)去除了两个集合重复的元素,Concat保留重复的元素。
比如,{1,2,3}和{3,4,5}的Union结果是{1,2,3,4,5},而Concat的结果是{1,2,3,3,4,5}。
4、差集 Except
如同数学中中的差集,集合[1,2,3]和集合[2,3]的交集是[1],代码和交并集类似。
/*C#写法*/List<User>result_list=big_list.Except(small_list).ToList()
5、去重 Distinct
如同数学中中的去重,集合[1,2,3]和集合[2,3,4]的去重集是[1],即从集合[1,2,3]中剔除集合[2,3,4]中出现的集合[1,2,3]中的元素,[1,2,3]中剔除[2,3],故结果集是[1]。代码和交并集类似。
/*C#写法*/List<User>result_list=big_list.Distinct(small_list).ToList()
6、合并 Zip
Zip函数可以按照元素顺序合并两个集合的元素组成一个装纳新元素的集合,集合[1,2,3]和集合[2,3,4],可以合并成[12,23,34]这种字符串拼接的集合,也可以合并成[{1,2},{2,3},{3,4}]这种新的匿名对象集合。
/*C#写法*///合并为字符串拼接的新字符串集合IEnumerable<string>unionList=list.Zip(salaryList, (i1, i2) =>i1.name+", "+i2.occupation); //合并为新的匿名对象集合varunionList=list.Zip(salaryList, (i1, i2) =>new { n=i1.name, m=i2.occupation });