数据库和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             小杨            男    英语        

两个个经典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;
        }
    }  

}

 

  

  

  

 

时间: 2024-11-05 11:38:50

数据库和linq中的 join(连接)操作的相关文章

LinQ中合并、连接、相交、与非查询

LinQ中Union合并查询:连接不同的集合,自动过滤相同项:延迟.即是将两个集合进行合并操作,过滤相同的项 var cities = (from p in mylinq.System_Places where p.PID == place select p).Union( from q in mylinq.System_Places where q.Parentid==place select q ); LinQ中的Concat连接查询:连接不同的集合,不会自动过滤相同项:延迟. (from 

php大力力 [024节]PHP中的字符串连接操作(2015-08-27)

2015-08-27 php大力力024.PHP中的字符串连接操作 PHP中的字符串连接操作  阅读:6185次   时间:2012-03-25 PHP字符串的连接的简单实例 时间:2013-12-30 很多时候我们需要将几个字符串连接起来显示,在PHP中,字符串之间使用“点”来连接,也就是英文中的句号”.”,具体使用方式如下 //定义字符串 $str1 = "Hello World!"; $str2 = "Welcome to HutaoW's BLOG!"; /

SQL中的join连接查询

inner join(交集 ,自然连接, 简写成join) 是最普通的连接查询,相当于早期根据where条件连接的查询 outer join(并集或部分并集,左表 + 右表) left [outer] join(左表产生完全集,右表有则匹配,没有则为null) right [outer] join(右表产生完全集,左表有则匹配,没有则为null) full [outer] join(并集) cross join(笛卡尔积,左表 * 右表) 开发中基本不用

LINQ系列:LINQ to SQL Join连接

1. 一对多 var expr = context.Products .Where(p => p.Category.CategoryName == "LINQ to SQL" && p.UnitPrice > 10m) .Select(p => new { p.ProductID, p.ProductName }); var expr = from p in context.Products where p.Category.CategoryName

Linq中eft join之大坑

1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Data; 5 using System.IO; 6 using System.Linq; 7 using Newtonsoft.Json; 8 9 namespace CLibrary.ConsoleApp 10 { 11 class Program 12 { 13 static void Main(str

MR的join连接操作

多表连接:将连接键(id)作为k2,v2采用自定义的Writable,writable中包含以下字段:标志位字段+业务字段(可能多个):reduce端做笛卡尔积. 自连接(单表关联):对于给定的数据的key value 调换,并作些标记予以区别. map端连接: 1.前提条件:小表尽可能小,一般情况在几十兆下: 2.DistributedCache:分布式缓存 原文地址:https://www.cnblogs.com/lyr999736/p/9381701.html

【spark】示例:连接操作

我们有这样两个文件 任务:找出用户评分平均值大于4的电影. 我们看两个文件结果,第一个文件有电影的ID和名字,第二个文件有电影的ID和所有用户的评分 对于任务结果所需要的数据为电影ID,电影名字,平均评分.平均评分用所有用户评分总和/用户数来求出 1.我们先计算电影的评分 (1)先读取电影评分文件 (2)取数据 我们看到每行的数据是通过::来进行连接的,然后我们需要的是第二列的电影ID以及第二列的评分. 我们把两个有用的数据取出来,组成键值对的形式. 为什么要组成键值对的形式? 数据中每个用户的

数据库中的左连接(left join)和右连接(right join)区别

Left Join / Right Join /inner join相关 关于左连接和右连接总结性的一句话: 左连接where只影向右表,右连接where只影响左表. Left Join select * from tbl1 Left Join tbl2 where tbl1.ID = tbl2.ID 左连接后的检索结果是显示tbl1的所有数据和tbl2中满足where 条件的数据. 简言之 Left Join影响到的是右边的表 Right Join select * from tbl1 Rig

LINQ中的连接(join)用法示例

Linq中连接主要有组连接.内连接.左外连接.交叉连接四种.各个用法如下. 1. 组连接 组连接是与分组查询是一样的.即根据分组得到结果. 如下例,根据publisther分组得到结果. 使用组连接的查询语句如下: //使用组连接 var GroupQuery = from publisher in SampleData.Publishers join book in SampleData.Books on publisher equals book.Publisher into publish