连接join
--1.内连接
--2.外连接:1>左外联接 2>右外连接 3>完全外连接
--3.自连接
create table TestJoin1Emp
(
EmpId int identity(1,1) primary key,
EmpName varchar(50),
EmpDeptid int
)
insert into TestJoin1Emp values('长孙娜',1)
insert into TestJoin1Emp values('李四',2)
insert into TestJoin1Emp values('八戒',3)
insert into TestJoin1Emp values('悟空',2)
insert into TestJoin1Emp values('玄奘',1)
create table TestJoin2Dept
(
DeptId int identity(1,1) primary key,
DeptName varchar(50)
)
select * from TestJoin2Dept
insert into TestJoin2Dept values('市场部')
insert into TestJoin2Dept values('研发部')
insert into TestJoin2Dept values('行政部')
select * from TestJoin1Emp
select * from TestJoin2Dept
--两张表进行连接的第一步,表进行交叉,生成一个大的结果集,叫做:笛卡尔积
select * from TestJoin1Emp,TestJoin2Dept
--下面的查询方式获取的就是两张表的笛卡尔积,然后根据条件筛选出符合条件的记录
select
员工编号=emp.EmpId,
姓名=emp.EmpName,
部门名称=dept.DeptName
from TestJoin1Emp emp,TestJoin2Dept dept
where emp.EmpDeptid=dept.DeptId
--【内连接】,内连接,仅仅筛选那些两张表中都能够匹配的那些记录
--把上面的这种写法替换成下面的这种写法,下面的这种写法使用的就是【内连接】inner join
select
员工编号=emp.EmpId,
姓名=emp.EmpName,
部门名称=dept.DeptName
from TestJoin1Emp emp
inner join TestJoin2Dept dept on emp.EmpDeptid=dept.DeptId
--练习
--案例1:查询所有学生的姓名、年龄及所在班级
select * from TblClass
select * from TblStudent
select
TblStudent.tsname,
TblStudent.tsage,
TblClass.TclassName
from TblStudent
inner join TblClass on TblStudent.tsclassid=TblClass.tclassId
--案例2:查询年龄超过20岁的学生的姓名、年龄及所在班级
select
TblStudent.tsname,
TblStudent.tsage,
TblClass.TclassName
from TblStudent
inner join TblClass on TblStudent.tsclassid=TblClass.tclassId
where tblstudent.tsage>20
--案例3:查询学生姓名、年龄、班级及成绩
select
TblStudent.tsname,
TblStudent.tsage,
TblClass.TclassName,
tblscore.tenglish,
tblscore.tmath
from TblStudent
inner join TblClass on TblStudent.tsclassid=TblClass.tclassId
inner join TblScore on TblStudent.tsid=TblScore.tsid
--案例4:查询所有学生(参加及未参加考试的都算)及成绩
--这里不能用内连接,内连接只是筛选那些在两个表中可以匹配的记录
--无法筛选那些没有匹配到的记录
--查询的是所有的学生,所以必须将所有学生的数据都显示出来
--这里需要使用左外联或者是右外联
--左外联表示显示左表中的全部数据,以及右表中的那些匹配的数据,对于左表中有,但是右表中没有匹配的那些数据显示为null
--left join 表达式左边的表就叫做“左表”,右边的就叫做“右表”
select * from TblScore
select * from TblStudent
--下面的两个查询结果一致,上面使用左连接,下面使用右连接
--这两个查询的主表都是TblStudent(学生表)
--左连接
select
stu.tsname,
stu.tsage,
英语=score.tenglish,
数学=score.tmath
from TblStudent as stu
left outer join TblScore as score on stu.tsid=score.tsid
--右连接
select
stu.tsname,
stu.tsage,
英语=score.tenglish,
数学=score.tmath
from TblScore as score
right outer join TblStudent as stu on stu.tsid=score.tsid
--外连接是通过3步,执行完毕的。
--1.笛卡尔积2.根据筛选条件进行内连接3.添加外部行
--案例5:请查询出所有没有参加考试(在成绩表中不存在的学生)的学生的姓名
--下面的查询结果是所有与参加考试的学生的姓名和成绩
select
ts.tsid,
ts.tsname,
score.tenglish,
score.tmath
from TblStudent as ts
inner join TblScore as score on ts.tsid=score.tsid
--要筛选那些没有参加考试的同学,不能用<>来进行内联接,那样会返回很多的数据
--这是应为他们第一步是查询出来的笛卡尔积,然后从笛卡尔积里面进行条件筛选
--所以直接使用<>会把很多我们认为的废数据给筛选出来
select
ts.tsid,
ts.tsname,
score.tenglish,
score.tmath
from TblStudent as ts inner join TblScore as score on ts.tsid<>score.tsid
--要筛选那些没有参加考试的学生的信息,其实就是要筛选那些在考试表中没有出现过的那些学生信息
--思路:可以先通过外连接查询出所有学生的信息,然后找那些成绩为null的,这些就是没有参加考试的学生的信息
--1.左连接实现
select
*
from TblStudent as stu
left join TblScore as score on stu.tsid=score.tsid
where score.tscoreId is null
--2.右连接实现
select
*
from TblScore as stu
right join TblStudent as score on stu.tsid=score.tsid
where score.tscoreId is null
--下面的两个查询方式中,在数据量不大的时候使用连接效率稍微高点
--数据量大的时候没有哪个效率更高...
--子查询
select
员工编号=emp.empId,
员工姓名=emp.EmpName,
部门名称=(select DeptName from TestJoin2Dept as dept where dept.deptId=emp.empDeptid)
from TestJoin1Emp as emp
--连接
select
emp.empid,
emp.empName,
dept.DeptName
from TestJoin1Emp as emp inner join TestJoin2Dept as dept on dept.deptId=emp.empDeptid
--自连接
--菜单信息,主键和父级序号,这里显示的是父级序号的ID
--如果我们想要直接显示上级菜单的名称而不是名称,则可以使用子查询或者自连接来查询
select * from NIS_ADDINS
select ID,ZYMC,PARENT_ID from NIS_ADDINS
--使用内连接,但是这种时候如果某个菜单没有父级菜单则无法返回数据
select
e1.ID,
e1.ZYMC,
e1.PARENT_ID,
e2.ZYMC
from NIS_ADDINS as e1
inner join NIS_ADDINS as e2 on e1.PARENT_ID=e2.ID
--使用外链接,如果没有父级菜单也会查询出来
select
e1.ID,
e1.ZYMC,
e1.PARENT_ID,
e2.ZYMC
from NIS_ADDINS as e1
left outer join NIS_ADDINS as e2 on e1.PARENT_ID=e2.ID