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
小明 男   数学
小明 男   语文
小明 男    英语
小黄 男   数学
小黄 男   语文
小黄 男   英语
小红 女    数学
小红 女   语文
小红 女   英语
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
小明 男 数学
小明 男 语文
小明 男 英语
小黄 男 数学
小黄 男 语文
小黄 男 英语
小红 女 数学
小红 女 语文
小红 女 英语
小杨 男 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
小明 男 数学
小明 男 语文
小明 男 英语
小明 男 数学
小明 男 语文
小明 男 英语
小明 男 数学
小明 男 语文
小明 男 英语
小明 男 数学
小明 男 语文
小明 男 英语
小黄 男 数学
小黄 男 语文
小黄 男 英语
小黄 男 数学
小黄 男 语文
小黄 男 英语
小黄 男 数学
小黄 男 语文
小黄 男 英语
小黄 男 数学
小黄 男 语文
小黄 男 英语
小红 女 数学
小红 女 语文
小红 女 英语
小红 女 数学
小红 女 语文
小红 女 英语
小红 女 数学
小红 女 语文
小红 女 英语
小红 女 数学
小红 女 语文
小红 女 英语
小杨 男 数学
小杨 男 语文
小杨 男 英语
小杨 男 数学
小杨 男 语文
小杨 男 英语
小杨 男 数学
小杨 男 语文
小杨 男 英语
小杨 男 数学
小杨 男 语文
小杨 男 英语

两个个经典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[] { "", "小明", "男" });
student.Rows.Add(new object[] { "", "小黄", "男" });
student.Rows.Add(new object[] { "", "小红", "女" });
student.Rows.Add(new object[] { "", "小杨", "男" });
return student;
} public static DataTable GetCourse()
{
DataTable course = new DataTable();
course.Columns.Add("studentId");
course.Columns.Add("courseName");
course.Rows.Add(new object[] { "", "数学" });
course.Rows.Add(new object[] { "", "英语" });
course.Rows.Add(new object[] { "", "语文" });
course.Rows.Add(new object[] { "", "数学" });
course.Rows.Add(new object[] { "", "英语" });
course.Rows.Add(new object[] { "", "语文" });
course.Rows.Add(new object[] { "", "数学" });
course.Rows.Add(new object[] { "", "英语" });
course.Rows.Add(new object[] { "", "语文" });
course.Rows.Add(new object[] { "", "数学" });
course.Rows.Add(new object[] { "", "英语" });
course.Rows.Add(new object[] { "", "语文" });
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 ;
int hashId = a.id == null ? : a.id.GetHashCode();
int hashName = a.name == null ? : a.id.GetHashCode();
int hashSex = a.sex == null ? : a.sex.GetHashCode();
int hashCourse = a.course == null ? : a.course.GetHashCode();
return hashId ^ hashName ^ hashSex ^ hashCourse;
}
} }

 

  

  

  

 

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

  1. EF Linq中的左连接Left Join查询

    linq中的join是inner join内连接,就是当两个表中有一个表对应的数据没有的时候那个关联就不成立. 比如表A B的数据如下 from a in A join b in B on a.BId ...

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

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

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

    2015-08-27 php大力力024.PHP中的字符串连接操作 PHP中的字符串连接操作  阅读:次   时间:2012-03-25 PHP字符串的连接的简单实例 时间:2013-12-30 很多 ...

  4. sql语句中的join连接(左连接、右连接、全连接、内连接)

    内部连接(inner join): select * from d_user a inner join D_ORGANIZATION b on a.COMPANY_XID=b.ID  内部链接也是排他 ...

  5. SQL中的join连接查询

      inner join(交集 ,自然连接, 简写成join)   是最普通的连接查询,相当于早期根据where条件连接的查询     outer join(并集或部分并集,左表 + 右表)   le ...

  6. LINQ系列:LINQ to SQL Join连接

    1. 一对多 var expr = context.Products .Where(p => p.Category.CategoryName == "LINQ to SQL" ...

  7. Linq中left join之多表查询

    using System; using System.Collections; using System.Collections.Generic; using System.Data; using S ...

  8. 巧用JS中的join方法操作字符串

    1.将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符 /** *把数组转换成特定符号分割的字符串 */ function arrayToString(arr,s ...

  9. PostgreSQL中的表连接操作

随机推荐

  1. javascript高级特性(面向对象)

    javascript高级特性(面向对象): * 面向对象: * 面向对象和面向过程的区别: * 面向对象:人就是对象,年龄\性别就是属性,出生\上学\结婚就是方法. * 面向过程:人出生.上学.工作. ...

  2. 关于数据库中varchar/nvarchar类型数据的获取注意事项

    当在页面后台获取数据库表中某字段的数据时,需注意该数据的类型.防止因实际数据的字符长度因达不到指定数据类型规定的字符长度而导致空格的占位符. 比如: MSSQL中某一表的结构如下:   表中的数据: ...

  3. 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析

    我的预想情况 一般情况下,当用户登录一个站点后,如果长时间没有发生任何动作,当用户再次点击时,会被强制登出并且跳转到登录页面, 提醒用户重新登录.现在我已经为站点整合了CAS,并且已经实现了单点登录以 ...

  4. poj2236 基础并查集

    题目链接:http://poj.org/problem?id=2236 题目大意:城市网络由n台电脑组成,因地震全部瘫痪,现在进行修复,规定距离小于等于d的电脑修复之后是可以直接相连 进行若干操作,O ...

  5. php生成短网址的思路与方法

    生成短网址的思路以及使用php生成短网址的实现方法. 生成短网址的思路:如果把短网址还原了,你知道是个什么样子的吗?比如:http://www.jbxue.com/sitejs-17300-1.htm ...

  6. JAVA-POI实现EXCEL的读写

    想要完成JAVA读写EXCEL,首先需要JAVA-POI包的支持,百度搜索即可找到资源,不再赘述: POI-新增EXCEL并输入内容 package com.gsh.test.poi; import ...

  7. Mysql主从复制的配置(双机互为主从)

    目的: 让两台mysql服务器可以互为主从提供同步服务. 优点: 1. mysql的主从复制的主要优点是同步"备份", 在从机上的数据库就相当于一个(基本实时)备份库. 2. 在主 ...

  8. iOS 摇一摇的实现-备用

    - (void)viewDidLoad { [super viewDidLoad]; [[UIApplication sharedApplication] setApplicationSupports ...

  9. Deep Residual Learning for Image Recognition(MSRA-深度残差学习)

    转自:http://blog.csdn.net/solomonlangrui/article/details/52455638   ABSTRACT:           神经网络的训练因其层次加深而 ...

  10. ural 1215 Exactness of Projectile Hit

    #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> # ...