zoukankan      html  css  js  c++  java
  • 数据库和linq中的 join(连接)操作

    sql中的连接

    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.studentId
    where 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.studentId
    where 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.studentId
    where s.studentId is null or c.studentId is null
    

    结果

    studentId	name	sex	courseName
    4         	小杨     男	NULL
    NULL	     NULL	NULL	数学        
    NULL	     NULL	NULL	语文        
    NULL	     NULL	NULL	英语        
    

    笛卡儿积(cross join) 

    select s.* ,c.courseName 
    from student s
    cross join course c 

    结果

    studentId    name    sex    courseName
    1             小明            男    数学        
    1             小明            男    语文        
    1             小明            男    英语        
    1             小明            男    数学        
    1             小明            男    语文        
    1             小明            男    英语        
    1             小明            男    数学        
    1             小明            男    语文        
    1             小明            男    英语        
    1             小明            男    数学        
    1             小明            男    语文        
    1             小明            男    英语        
    2             小黄            男    数学        
    2             小黄            男    语文        
    2             小黄            男    英语        
    2             小黄            男    数学        
    2             小黄            男    语文        
    2             小黄            男    英语        
    2             小黄            男    数学        
    2             小黄            男    语文        
    2             小黄            男    英语        
    2             小黄            男    数学        
    2             小黄            男    语文        
    2             小黄            男    英语        
    3             小红            女    数学        
    3             小红            女    语文        
    3             小红            女    英语        
    3             小红            女    数学        
    3             小红            女    语文        
    3             小红            女    英语        
    3             小红            女    数学        
    3             小红            女    语文        
    3             小红            女    英语        
    3             小红            女    数学        
    3             小红            女    语文        
    3             小红            女    英语        
    4             小杨            男    数学        
    4             小杨            男    语文        
    4             小杨            男    英语        
    4             小杨            男    数学        
    4             小杨            男    语文        
    4             小杨            男    英语        
    4             小杨            男    数学        
    4             小杨            男    语文        
    4             小杨            男    英语        
    4             小杨            男    数学        
    4             小杨            男    语文        
    4             小杨            男    英语        
    View Code

    两个个经典sql问题的解法

    一、取出没有选课的学生的信息

    方法一:利用left excluding join

    select s.* 
    from student s
    left join course c 
    on s.studentId=c.studentId
    where c.studentId is null
    

    结果

    studentId	name	sex
    4         	小杨     男
    

    方法二:利用exists

    思路:先找到有选课的学生的信息然后通过exists或not exists来取出想要的数据

    select * from student st 
    where not exists(
    	select s.* ,c.courseName
    	from student s
    	inner join course c 
    	on s.studentId=c.studentId
    	where st.studentId=s.studentId
    )
    

    结果跟方法一的一样

    二、取出有选课的学生的信息

    select * from student st 
    where exists(
    	select s.* ,c.courseName
    	from student s
    	inner join course c 
    	on s.studentId=c.studentId
    	where st.studentId=s.studentId
    )
    

    结果

    studentId	name	     sex
    1         	小明        	男
    2         	小黄        	男
    3         	小红        	女
    

    Linq 中的连接

    在linq中同样能实现上述sql的连接操作

    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

     

      

      

      

     

  • 相关阅读:
    English,The Da Vinci Code, Chapter 23
    python,meatobject
    English,The Da Vinci Code, Chapter 22
    English,The Da Vinci Code, Chapter 21
    English,The Da Vinci Code, Chapter 20
    English,The Da Vinci Code, Chapter 19
    python,xml,ELement Tree
    English,The Da Vinci Code, Chapter 18
    English,The Da Vinci Code, Chapter 17
    English,The Da Vinci Code, Chapter 16
  • 原文地址:https://www.cnblogs.com/fuhai/p/5629355.html
Copyright © 2011-2022 走看看