SQL多表查询最直接最终.docx

上传人:b****3 文档编号:26861182 上传时间:2023-06-23 格式:DOCX 页数:13 大小:148.60KB
下载 相关 举报
SQL多表查询最直接最终.docx_第1页
第1页 / 共13页
SQL多表查询最直接最终.docx_第2页
第2页 / 共13页
SQL多表查询最直接最终.docx_第3页
第3页 / 共13页
SQL多表查询最直接最终.docx_第4页
第4页 / 共13页
SQL多表查询最直接最终.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

SQL多表查询最直接最终.docx

《SQL多表查询最直接最终.docx》由会员分享,可在线阅读,更多相关《SQL多表查询最直接最终.docx(13页珍藏版)》请在冰豆网上搜索。

SQL多表查询最直接最终.docx

SQL多表查询最直接最终

SQL多表连接查询总结

1SQL查询的基本原理

1.1单表查询

根据where条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的);然后根据select的选择列选择相应的列进行返回最终结果。

1.2两表连接查询

对两表求积(笛卡尔积),再用on条件和连接类型进行过滤形成中间表;然后根据where条件过滤中间表的记录,并根据select指定的列返回查询结果。

1.3多表连接查询

先对from后第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据where条件过滤中间表的记录,并根据select指定的列返回查询结果。

1.4SQL逻辑处理执行顺序

1.4.1T-SQL逻辑查询的各个阶段

(5)SELECTDISTINCTTOP(

(1)FROMJOINON 

(2)WHERE

(3)GROUPBY

(4)HAVING

(6)ORDERBY

1.4.2T-SQL在查询各个阶级分别干了什么

(1)FROM阶段

FROM阶段标识出查询的来源表,并处理表运算符。

在涉及到联接运算的查询中(各种join),主要有以下几个步骤:

a.求笛卡尔积。

不论是什么类型的联接运算,首先都是执行交叉连接(crossjoin),求笛卡儿积,生成虚拟表VT1-J1。

b.ON筛选器。

这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的条件进行筛选,让条件取值为true的行通过了考验,生产VT1-J2。

c.添加外部行。

如果指定了outerjoin,还需要将没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。

  经过以上步骤,FROM阶段就完成了。

概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot)。

(2)WHERE阶段

  WHERE阶段是根据中条件对VT1-J3中的行记录进行筛选,让条件成立的行才会插入到VT2中。

(3)GROUPBY阶段

  GROUPBY阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。

最后每个分组只有一行。

(4)HAVING阶段

  该阶段根据HAVING子句中出现的条件对VT3的分组进行筛选,并将符合条件的组插入到VT4中。

(5)SELECT阶段

  这个阶段是投影的过程,选择所连接的表中的字段(列),产生VT5。

这个步骤一般按下列顺序进行

  a.计算SELECT列表中的表达式,生成VT5-1。

  b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2。

  c.若有TOP,则根据ORDERBY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3。

(6)ORDERBY阶段

 根据ORDERBY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6。

2多表连接的类型

2.1交叉连接(crossjoin)

交叉连接(CROSSJOIN):

有两种形式,分为显式的和隐式的,都不带where条件。

返回的是两表的乘积,也叫笛卡尔积。

下面的语句1和语句2的结果是相同的。

2.1.1隐式的交叉连接

隐式的交叉连接,在语句中是没有CROSSJOIN的。

语句1:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefroms,sc;

结果如下:

2.1.2显式的交叉连接

显式的交叉连接,在语句中使用crossjoin。

语句2:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromscrossjoinsc;

结果如下:

语句1和语句2的结果是相同的。

2.2内连接(innerjoin)

内连接有两种形式,也是分显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。

(所谓的链接表就是数据库在做查询过程中形成的中间表)。

2.2.1隐式的内连接

隐式的内连接,在语句中没有INNERJOIN。

语句3:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefroms,scwheres.sno=sc.sno;

结果如下:

2.2.2显式的内连接

显式的内连接,一般称为内连接,使用INNERJOIN。

语句4:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromsinnerjoinscons.sno=sc.sno;

结果如下:

语句3和语句4的结果是相同的。

2.3外连接(outerjoin)

外连接不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。

外连接分三类:

左外连接(LEFTOUTERJOIN)、右外连接(RIGHTOUTERJOIN)和全外连接(FULLOUTERJOIN)。

三者的共同点是都返回符合连接条件和查询条件(即:

内连接)的数据行。

不同点如下:

左外连接还返回左表中不符合连接条件单符合查询条件的数据行;右外连接还返回右表中不符合连接条件单符合查询条件的数据行;全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。

全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即“全外=左外UNION右外”。

左表就是在“(OUTERJOIN)”关键字左边的表,右表当然就是右边的了。

在三种类型的外连接中,OUTER关键字是可省略的。

2.3.1左外连接(leftouterjoin)

语句5:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromsleftjoinscons.sno=sc.sno;

结果如下:

2.3.2右外连接(rightouterjoin)

语句6:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromsrightjoinscons.sno=sc.sno;

结果如下:

2.3.4全外连接

全外连接(FULLOUTERJOIN),除了返回符合条件的数据外,还返回左表和右表不符合条件的数据行。

语句7:

selects.sno,s.sname,s.nianl,s.sex,ame,sc.sccre,c.teacherfromsfulljoinscons.sno=sc.snofulljoincono=o;

结果如下:

MySQL是不支持全外连接的,这里给出的写法适合Oracle和DB2。

但是可以通过左外和右外求合集来获取全外连接的查询结果。

下图是MySQL语句在Oracle11g下测试的结果:

语句8:

selects.sno,s.sname,s.nianl,s.sex,ame,sc.sccre,c.teacherfromsleftjoinscons.sno=sc.snoleftjoincono=o

union

selects.sno,s.sname,s.nianl,s.sex,ame,sc.sccre,c.teacherfromsrightjoinscons.sno=sc.snorightjoincono=o;

结果如下:

语句7和语句8的查询结果是相同的。

2.4联合连接(unionjoin)

这是一种很少见的连接方式。

Oracle、MySQL均不支持,其作用是:

找出全外连接和内连接之间差异的所有行。

这在数据分析中排错中比较常用。

也可以利用数据库的集合操作来实现此功能。

2.5自然连接(naturaljoin)

说真的,这种连接查询没有存在的价值,既然是SQL2标准中定义的,就给出个例子看看吧。

自然连接无需指定连接列,SQL会检查两个表中是否相同名称的列,且假设他们在连接条件中使用,并且在连接条件中仅包含一个连接列。

不允许使用ON语句,不允许指定显示列,显示列只能用*表示(ORACLE环境下测试的)。

对于每种连接类型(除了交叉连接外),均可指定NATURAL。

下面给出几个例子:

2.5.1内自然连接

语句9:

select*fromsnaturalinnerjoinsc;

结果如下:

2.5.2左自然连接

语句10:

select*fromsnaturalleftjoinsc;

结果如下:

2.5.3右自然连接

语句11:

select*fromsnaturalrightjoinsc;

结果如下:

3on条件和where条件的区别

on条件是过滤两个链接表笛卡尔积形成中间表的约束条件;where条件是在有on条件的查询语句中过滤中间表的约束条件。

在没有on的单表查询中,是限制物理表或者中间查询结果返回记录的约束。

在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。

从这里可以看出,将where条件移入on后面是不恰当的。

推荐的做法是:

on只进行连接操作,where只过滤中间表的记录。

语句12:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromsrightjoinscons.sno=sc.sno

wheresc.sccre=29;

将语句12中的WHERE条件放到ON后面。

语句13:

selects.sno,s.sname,s.nianl,s.sex,sc.sccrefromsrightjoinscons.sno=sc.snoandsc.sccre=29;

结果如下:

从语句12和语句13查询的结果来看,显然是不相同的,语句8显示的结果是难以理解的。

因此,推荐在写连接查询的时候,ON后面只跟连接条件,而对中间表限制的条件都写到WHERE子句中。

4附件:

--附件中内容为数据库脚本。

--

createtables(/*学生表*/

snochar(10)primarykey,

snamechar(10),

nianlint,

sexchar(10)

);

createtablesc(/*分数表*/

snochar(10),

cnochar(10),

sccreint,

primarykey(sno,cno)

);

createtablec(/*课程表*/

cnochar(10)primarykey,

cnamechar(10),

teacherchar(10)

);

insertintosvalues('001','张三','18','男');

insertintosvalues('002','李四','16','男');

insertintosvalues('003','王五','19','女');

insertintosvalues('004','周六','15','男');

insertintosvalues('005','张七','17','女');

insertintoscvalues('001','01','98');

insertintoscvalues('002','01','43');

insertintoscvalues('003','01','29');

insertintoscvalues('004','01','45');

insertintoscvalues('006','01','97');

insertintoscvalues('001','02','98');

insertintoscvalues('002','02','45');

insertintoscvalues('003','02','76');

insertintoscvalues('004','02','49');

insertintoscvalues('006','02','77');

insertintoscvalues('001','03','93');

insertintoscvalues('002','03','42');

insertintoscvalues('003','03','77');

insertintoscvalues('004','03','45');

insertintoscvalues('006','03','74');

insertintocvalues('01','语文','刘玉娟');

insertintocvalues('02','数学','周晓');

insertintocvalues('03','英语','屈水初');

commit;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 信息与通信

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1