数据库和linq中的 join(连接)操作
2016-06-30 11:11
387 查看
[b]sql中的连接[/b]
sql中的表连接有inner join,left join(left outer join),right join(right outer join),full join(full outer join),cross join
在此基础上我们能扩展出 left excluding join,right excluding join,full outer excluding join
注:left join是left outer join 的简写,即左连接和左外连接是一样的
首先定义两个比较经典的表
学生信息表和选课表
student
course
这两张表其实并不规范,course的studentId其实是一个外键,对应student的studentId,所以course的studentId不应该有5,不过为了测试方便,暂且这么写
内连接(inner join)
结果
左连接(left join)
结果
右连接
结果
全连接
结果
左不包含连接(left excluding join)
结果
右不包含连接(right excluding join)
结果
全不包含连接(Full outer excluding join)
结果
笛卡儿积(cross join)
结果
View Code
sql中的表连接有inner join,left join(left outer join),right join(right outer join),full join(full outer join),cross join
在此基础上我们能扩展出 left excluding join,right excluding join,full outer excluding join
注:left join是left outer join 的简写,即左连接和左外连接是一样的
首先定义两个比较经典的表
学生信息表和选课表
student
studentId name sex 1 小明 男 2 小黄 男 3 小红 女 4 小杨 男
course
studentId courseName 1 数学 1 语文 1 英语 2 数学 2 语文 2 英语 3 数学 3 语文 3 英语 5 数学 5 语文 5 英语
这两张表其实并不规范,course的studentId其实是一个外键,对应student的studentId,所以course的studentId不应该有5,不过为了测试方便,暂且这么写
内连接(inner join)
select s.* ,c.courseName from student s inner join course c on s.studentId=c.studentId
结果
studentId name sex courseName 1 小明 男 数学 1 小明 男 语文 1 小明 男 英语 2 小黄 男 数学 2 小黄 男 语文 2 小黄 男 英语 3 小红 女 数学 3 小红 女 语文 3 小红 女 英语
左连接(left join)
select s.* ,c.courseName from student s left join course c on s.studentId=c.studentId
结果
studentId name sex courseName 1 小明 男 数学 1 小明 男 语文 1 小明 男 英语 2 小黄 男 数学 2 小黄 男 语文 2 小黄 男 英语 3 小红 女 数学 3 小红 女 语文 3 小红 女 英语 4 小杨 男 NULL
右连接
select s.* ,c.courseName from student s right join course c on s.studentId=c.studentId
结果
studentId name sex courseName 1 小明 男 数学 1 小明 男 语文 1 小明 男 英语 2 小黄 男 数学 2 小黄 男 语文 2 小黄 男 英语 3 小红 女 数学 3 小红 女 语文 3 小红 女 英语 NULL NULL NULL 数学 NULL NULL NULL 语文 NULL NULL NULL 英语
全连接
select s.* ,c.courseName from student s full join course c on s.studentId=c.studentId
结果
studentId name sex courseName 1 小明 男 数学 1 小明 男 语文 1 小明 男 英语 2 小黄 男 数学 2 小黄 男 语文 2 小黄 男 英语 3 小红 女 数学 3 小红 女 语文 3 小红 女 英语 4 小杨 男 NULL NULL NULL NULL 数学 NULL NULL NULL 语文 NULL NULL NULL 英语
左不包含连接(left excluding join)
select s.* ,c.courseName from student s left join course c on s.studentId=c.studentIdwhere c.studentId is null
结果
studentId name sex courseName 4 小杨 男 NULL
右不包含连接(right excluding join)
select s.* ,c.courseName from student s right join course c on s.studentId=c.studentIdwhere s.studentId is null
结果
studentId name sex courseName NULL NULL NULL 数学 NULL NULL NULL 语文 NULL NULL NULL 英语
全不包含连接(Full outer excluding join)
select s.* ,c.courseName from student s full join course c on s.studentId=c.studentIdwhere s.studentId is null or c.studentId is null
结果
studentId name sex courseName 4 小杨 男 NULLNULL NULL NULL 数学
NULL NULL NULL 语文
NULL NULL NULL 英语
笛卡儿积(cross join)
select s.* ,c.courseName from student s cross join course c
结果
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; namespace LinqJoinTest { class Program { static void Main(string[] args) { DataTable student = GetStudent(); DataTable course = GetCourse(); Console.WriteLine("内连接"); IEnumerable<ResultModel> result = InnerJoin(student, course); foreach(ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("左连接"); result = LeftJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("右连接"); result = RightJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("全连接"); result = AllJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("左不包含连接"); result = LeftOuterJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("右不包含连接"); result = RightOuterJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.WriteLine("全不包含连接"); result = AllOuterJoin(student, course); foreach (ResultModel item in result) { Console.WriteLine(string.Format("{0},{1},{2},{3}", item.id, item.name, item.sex, item.course)); } Console.ReadKey(); } public static DataTable GetStudent() { DataTable student = new DataTable(); student.Columns.Add("studentId"); student.Columns.Add("name"); student.Columns.Add("sex"); student.Rows.Add(new object[] { "1", "小明", "男" }); student.Rows.Add(new object[] { "2", "小黄", "男" }); student.Rows.Add(new object[] { "3", "小红", "女" }); student.Rows.Add(new object[] { "4", "小杨", "男" }); return student; } public static DataTable GetCourse() { DataTable course = new DataTable(); course.Columns.Add("studentId"); course.Columns.Add("courseName"); course.Rows.Add(new object[] { "1", "数学" }); course.Rows.Add(new object[] { "1", "英语" }); course.Rows.Add(new object[] { "1", "语文" }); course.Rows.Add(new object[] { "2", "数学" }); course.Rows.Add(new object[] { "2", "英语" }); course.Rows.Add(new object[] { "2", "语文" }); course.Rows.Add(new object[] { "3", "数学" }); course.Rows.Add(new object[] { "3", "英语" }); course.Rows.Add(new object[] { "3", "语文" }); course.Rows.Add(new object[] { "5", "数学" }); course.Rows.Add(new object[] { "5", "英语" }); course.Rows.Add(new object[] { "5", "语文" }); return course; } /// <summary> /// 内连接 /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> InnerJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from s in student.Select() join c in course.Select() on s["studentId"].ToString() equals c["studentId"].ToString() select new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course = c["courseName"].ToString() }; //查询表达式语法 result = student.Select() .Join(course.Select(), s => s["studentId"].ToString(), c => c["studentId"].ToString(), (s, c) => new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course = c["courseName"].ToString() }); return result; } /// <summary> /// 左连接(左外连接) linq中只有左连接,右连接只要把数据集合顺序倒转就行了 /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> LeftJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from s in student.Select() join c in course.Select() on s["studentId"].ToString() equals c["studentId"].ToString() into temple from t in temple.DefaultIfEmpty() select new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course = t==null?"Null":t["courseName"].ToString() }; //查询表达式语法 result = student.Select().GroupJoin(course.Select(), s => s["studentId"].ToString(), c => c["studentId"].ToString(), (s, c) => new { s, c }).SelectMany(g => g.c.DefaultIfEmpty(), (item, c) => new ResultModel { id = item.s["studentId"].ToString(), name = item.s["name"].ToString(), sex = item.s["sex"].ToString(), course = c == null ? "Null" : c["courseName"].ToString() }); return result; } /// <summary> /// 右连接(右外连接) /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> RightJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from c in course.Select() join s in student.Select() on c["studentId"].ToString() equals s["studentId"].ToString() into temple from t in temple.DefaultIfEmpty() select new ResultModel { id = t == null ? "Null" : t["studentId"].ToString(), name = t == null ? "Null" : t["name"].ToString(), sex = t == null ? "Null" : t["sex"].ToString(), course = c["courseName"].ToString() }; //查询表达式语法 result = course.Select().GroupJoin(student.Select(), s => s["studentId"].ToString(), c => c["studentId"].ToString(), (s, c) => new { s, c }).SelectMany(g => g.c.DefaultIfEmpty(), (item, c) => new ResultModel { id = c == null ? "Null" : c["studentId"].ToString(), name = c == null ? "Null" : c["name"].ToString(), sex = c == null ? "Null" : c["sex"].ToString(), course =item.s["courseName"].ToString() }); return result; } /// <summary> /// 全连接(全外连接) /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> AllJoin(DataTable student, DataTable course) { IEnumerable<ResultModel> left = LeftJoin(student, course); IEnumerable<ResultModel> right = RightJoin(student, course); //比较器 IEqualityComparer<ResultModel> ec = new EntityComparer(); return left.Union(right, ec); } /// <summary> /// 左不包含连接 /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> LeftOuterJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from s in student.Select() join c in course.Select() on s["studentId"].ToString() equals c["studentId"].ToString() into temple from t in temple.DefaultIfEmpty() where t==null select new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course ="Null" }; //查询表达式语法 result = student.Select().GroupJoin(course.Select(), s => s["studentId"].ToString(), c => c["studentId"].ToString(), (s, c) => new { s, c }) .SelectMany(g => g.c.DefaultIfEmpty(), (item, c) => new { item,c}).Where(item => item.c== null) .Select(item=>new ResultModel { id = item.item.s["studentId"].ToString(), name = item.item.s["name"].ToString(), sex = item.item.s["sex"].ToString(), course ="Null" }); return result; } /// <summary> /// 右不包含连接 /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> RightOuterJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from c in course.Select() join s in student.Select() on c["studentId"].ToString() equals s["studentId"].ToString() into temple from t in temple.DefaultIfEmpty() where t==null select new ResultModel { id = "Null", name = "Null", sex = "Null", course = c["courseName"].ToString() }; //查询表达式语法 result = course.Select().GroupJoin(student.Select(), s => s["studentId"].ToString(), c => c["studentId"].ToString(), (s, c) => new { s, c }).SelectMany(g => g.c.DefaultIfEmpty(), (item, c) => new { item, c }).Where(item=>item.c==null) .Select(item => new ResultModel { id ="Null", name ="Null", sex = "Null" , course = item.item.s["courseName"].ToString() }); return result; } /// <summary> /// 全不包含连接 /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> AllOuterJoin(DataTable student, DataTable course) { IEnumerable<ResultModel> left = LeftOuterJoin(student, course); IEnumerable<ResultModel> right = RightOuterJoin(student, course); return left.Union(right); } /// <summary> /// 交叉连接(笛卡尔积) /// </summary> /// <param name="student"></param> /// <param name="course"></param> /// <returns></returns> public static IEnumerable<ResultModel> CrossJoin(DataTable student, DataTable course) { //Lambda表达式 var result = from s in student.Select() from c in course.Select() select new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course = c["courseName"].ToString() }; //查询表达式语法 result = student.Select() .SelectMany(c=>course.Select(), (s, c) => new ResultModel { id = s["studentId"].ToString(), name = s["name"].ToString(), sex = s["sex"].ToString(), course = c["courseName"].ToString() }); return result; } } public class ResultModel { public string id { get; set; } public string name { get; set; } public string sex { get; set; } public string course { get; set; } } public class EntityComparer : IEqualityComparer<ResultModel> { public bool Equals(ResultModel a, ResultModel b) { if (Object.ReferenceEquals(a, b)) return true; if (Object.ReferenceEquals(a, null) || Object.ReferenceEquals(b, null)) return false; return a.id == b.id && a.name == b.name && a.sex == b.sex&&a.course==b.course; } public int GetHashCode(ResultModel a) { if (Object.ReferenceEquals(a, null)) return 0; int hashId = a.id == null ? 0 : a.id.GetHashCode(); int hashName = a.name == null ? 0 : a.id.GetHashCode(); int hashSex = a.sex == null ? 0 : a.sex.GetHashCode(); int hashCourse = a.course == null ? 0 : a.course.GetHashCode(); return hashId ^ hashName ^ hashSex ^ hashCourse; } } }
View Code
相关文章推荐
- PLSQL Developer打开出现ORA-12541:TNS:no listener错误解决方法
- Oracle查询结果加一个'全部'条件
- 设置mysql外部ip可以访问的命令
- SQL Server 忘记所有登录账号解决方法
- oracle 的PACKAGE恢复过程
- oracle数据库读取操作系统的物理文件-转载,待完善
- 安装mysql中遇到的问题
- SQL的主键和外键约束
- 创建数据库utf8
- oracle函数之substr
- sql语句中字段的别名中含有括号时的解决办法
- DB2学习必须有的
- MongoDB 3.0以上版本设置访问权限、设置用户
- mysql 性能优化索引、缓存、分表、分布式实现方式。
- centos 设置oracle 开机自启动
- Oracle递归查询:使用prior实现树操作
- SQL Case When 嵌套
- Java中使用Jedis操作Redis
- mysql select不使用任何锁(select with nolock)
- MySQL数据单个数据太大,导入不进去