您的位置:首页 > 数据库

数据库和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

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

 

  

  

  

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: