一、用SQL自连接查询处理列之间的关系

SQL自身连接,可以解决很多问题。下面举的一个例子,就是使用了SQL自身连接,它解决了列与列之间的逻辑关系问题,准确的讲是列与列之间的层次关系。SQL代码如下:

 SELECT FIRST.CNumber, SECOND.PCNumber
FROM Course FIRST, Course SECOND
WHERE FIRST.PCNumber=SECOND.CNumber;

 在这个代码中,只涉及到一个表,即课程信息表COURSE(CNumber, CName, PCNumber),其中CNumber是该课程的课程号,PCNumber是该课程的先修课课程号。在FROM子句中,为Course表起了两个不同的别名,即FIRST和SECOND,即为Course表创建了两个不同的实例。查询时,使用了条件语句WHERE,要求FIRST表中的先修课号PCNumber同SECOND表中的课程号CNumber相同,而查询所需要的结果,是FIRST表的课程号CNumber和SECOND表中的PCNumber,那么查询结果,就应该是FIRST表中的课程号CNumber和该课程号所对应的间接先修课课程号。
  
  同样的查询,如果不使用自连接,而纯粹是对单表本身进行操作,那将是非常困难的。假设在这个表中,有两个元组(cnumber1, cname1, pcnumber1)和(cnumber2, cname2, pcnumber2),其中,pcnumber1=cnumber2。在同一个COURSE表上,关于课程号的信息,只有CNumber和PCNumber这两个属性,它们只能表示一个课程号(cnumber1)和该课程号直接先修课(pcnumber1=cnumber2)的一层关系。而间接先修课,需要求出cnumber1和pcnumber2的关系,这是一个二层关系。对于这个只能表示一层关系的表而言,如果纯粹对单表进行操作而不使用自然连接,那么一个可行的方案是,为Course表再增加一个列PPCNumber,令该列表示间接先修课,那么,通过三个列,就可以表示这种二层关系了。
  通过这个例子以及对这个例子的分析,我们可以初步得出结论,自连接查询,可以表示表中各列的层次关系。当所要查询的信息都出于同一个表,而又不能直接通过该表的各个列的直接层次关系得到最终结果的时候,那么应该考虑使用表的自连接查询。
  

二、SQL自连接查询表示其它关系

  除了处理前面例子中的列之间的层次关系之外,SQL自连接查询还可用于处理列之间的顺序关系、因果关系等多种逻辑关系。此外,SQL自身查询还可以用于处理单列本身的逻辑关系。下面的例子,就说明了对单列的逻辑关系的处理。

 SELECT FIRST.Num, FIRST Stop, SECOND.Stop
FROM Route FIRST, Route SECOND
WHERE FIRST.NUM=SECOND.NUM;

 这个代码中,只涉及到一个表Route(Num, Stop),这个表可以表示某一线路的火车的车站线路信息。Num表示该车的车次号,Stop表示该次车停靠的城市名称。上面的代码,可以求出某一线路的火车可以联通的任意两个城市的名称。
 在这里例子中,连接的操作对象只有Num这一个列,通过相同的车次号,找出该列车联通的任意两个城市的信息。在这个例子中,原来表Route中的每一个元组,只能表示车号和该车的某一站点的信息,实际上,这是“1Vs1”的映射关系。如果要表示两个站点的联通关系,那么就应该把两个“1Vs1”关系合并,形成“1Vs多”的关系。我们利用自连接,很容易地解决了这个关系扩充的问题。
下面的这里例子,是对单一的列进行连接处理:
 

 SELECT FIRST.Num, SECOND.Num, FIRST.Stop
FROM Route FIRST, Route SECOND
WHERE FRIST.Stop=SECOND.Stop;

  
  上面的SQL代码,求出了路经相同城市的车次的信息。原表中的车次和车站是“1Vs1”关系,通过自连接后,得到了车次和车站的“多Vs1”关系。

 一些自连接代码经典例子:

到目前为止,我们连接的都是两张不同的表,那么能不能对一张表进行自我连接呢?答案是肯定的。
有没有必要对一张表进行自我连接呢?答案也是肯定的。

表的别名:
一张表可以自我连接。进行自连接时我们需要一个机制来区分一个表的两个实例。
在FROM clause(子句)中我们可以给这个表取不同的别名, 然后在语句的其它需要使用到该别名的地方
用dot(点)来连接该别名和字段名。

我们在这里同样给出两个表来对自连接进行解释。
爱丁堡公交线路,

车站表:
stops(id, name)

公交线路表:
route(num, company, pos, stop)

关于这两个表更详细的解释可以参考这里:http://sqlzoo.cn/buses.htm

一、对公交线路表route进行自连接。

 SELECT * FROM route R1, route R2
WHERE R1.num=R2.num AND R1.company=R2.company

我们route表用字段(num, company)来进行自连接. 结果是什么意思呢?
你可以知道每条公交线路的任意两个可联通的车站。

二、用stop字段来对route(公交线路表)进行自连接。

 SELECT * FROM route R1, route R2
WHERE R1.stop=R2.stop;

查询的结果就是共用同一车站的所有公交线。这个结果对换乘是不是很有意义呢。

从这两个例子我们可以看出,自连接的语法结构很简单,但语意结果往往不是
那么容易理解。就我们这里所列出的两个表,如果运用得当,能解决很多实际问题,
例如,任意两个站点之间如何换乘。

 SELECT R1.company, R1.num
FROM route R1, route R2, stops S1, stops S2
WHERE R1.num=R2.num AND R1.company=R2.company
AND R1.stop=S1.id AND R2.stop=S2.id
AND S1.name='Craiglockhart'
AND S2.name='Tollcross'

  
  总结
  
  同其它连接相比,SQL自连接查询本身并没有什么特殊的。但是,在应用中,自连接查询因为其语法结构简单,而逻辑结构复杂,语义往往不是那么容易被人理解,因此,在使用时,经常令人觉得迷惑不解。但只要把自连接运用的得当,把单表看成是多表,牢固树立这一思维定式,我们会发现,自连接查询会为我们解决很多复杂的问题。

原文地址:https://www.cnblogs.com/Hadley-pu/p/sql_selfconnect.html

sql中自连接的使用的更多相关文章

  1. SQL中的连接(极客时间)

    SQL中的连接 关系型数据库的核心之一就是连接, 而在不同的标准中, 连接的写法上可能有区别, 最为主要的两个SQL标准就是SQL92和SQL99了, 后面的数字表示的是标准提出的时间. SQL92中 ...

  2. SQL中Round(),Floor(),Ceiling()函数的浅析

    项目中的一个功能模块上用到了标量值函数,函数中又有ceiling()函数的用法,自己找了一些资料,对SQL中这几个函数做一个简单的记录,方便自己学习.有不足之处欢迎拍砖补充 1.round()函数遵循 ...

  3. 关于sql中in 和 exists 的效率问题,in真的效率低吗

    原文: http://www.cnblogs.com/AdamLee/p/5054674.html 在网上看到很多关于sql中使用in效率低的问题,于是自己做了测试来验证是否是众人说的那样. 群众: ...

  4. 学习sql中的排列组合,在园子里搜着看于是。。。

    学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...

  5. SQL中distinct的用法

    SQL中distinct的用法   1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...

  6. hibernate中java类的成员变量类型如何映射到SQL中的数据类型变化

    hibernate映射文件??.hbm.xml配置映射元素详解--Hibernate映射类型 在从Hibernate的java的成员类型映射到SQL中的数据类型,其内映射方式它满足,SQL可以自己调制 ...

  7. C#调用SQL中的存储过程中有output参数,存储过程执行过程中返回信息

      C#调用SQL中的存储过程中有output参数,类型是字符型的时候一定要指定参数的长度.不然获取到的结果总是只有第一字符.本人就是由于这个原因,折腾了很久.在此记录一下,供大家以后参考! 例如: ...

  8. sql中case when语句的使用-来自网摘文章

    Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...

  9. SQL中inner join、outer join和cross join的区别

    对于SQL中inner join.outer join和cross join的区别简介:现有两张表,Table A 是左边的表.Table B 是右边的表.其各有四条记录,其中有两条记录name是相同 ...

随机推荐

  1. setOutputFormat called in an invalid state: 1

    在编写一个简单的录像应用程序的时候,爆出例如以下异常: E MediaRecorder: setOutputFormat called in an invalid state: 1 E Android ...

  2. LeetCode 5_Longest Palindromic Substring

    LeetCode 5_Longest Palindromic Substring  题目描写叙述: Given a string S, find the longest palindromic sub ...

  3. Python学习笔记24:Django搭建简单的博客站点(二)

    上一节说道怎样使用Django创建并执行一个项目.这节说怎样加入一个博客应用. 一 项目跟应用的关系 在加入应用之前,先来看看项目与应用之间有什么不同之处呢? 项目是针对一个特定的 Web 站点相关的 ...

  4. luogu2754 星际转移问题 网络流

    题目大意:地球与月球间有可容纳无限人的太空站,还有在太空站与星球间按周期行驶的.有固定容量的太空船,每一艘太空船从一个太空站驶往任一太空站耗时均为 1.地球上有一定数量的人,问所有人到月球最少需要多少 ...

  5. POJ1742 Coins 背包

    题目大意:给出一些钱币的价值和对应的数目,求在一定价值限定下这些钱币能凑成的价值数. 本题用多重背包直接拆分或二进制拆分法都太慢.说起处理一组物品,完全背包可算是比较效率高的,但是本题中物体的数目是有 ...

  6. android 更新ui

    https://www.cnblogs.com/rayray/p/3437048.html https://www.cnblogs.com/zhaoyanjun/p/5546683.html

  7. php获取uniqid

    md5(uniqid(microtime(true),true))

  8. Hdu-2892 area 计算几何 圆与凸多边形面积交

    题面 题意:有一个凸多边形岛屿,然后告诉你从高空(x,y,h)投下炸弹,爆炸半径r,飞机水平速度和重力加速度,问岛屿被炸了多少 题解:算出来岛屿落地位置,再利用圆与凸多边形面积交 #include&l ...

  9. Jsoup的简单的使用示例

    利用Jsoup中的相关方法实现网页中的数据爬去,本例子爬去的网页为比较流行的programmableweb中的mashup描述内容,然后为数据库中存在的mashup添加相应的描述. package c ...

  10. Arduino-1602-LiquidCrystal库

    前言:LiquidCrystal是一个1602的IIC库,使用IIC协议可以极大节约用线数量,十分方便.当然,前提是1602要使用LCD1602 I2C模块. 一.库函数快速查询 LiquidCrys ...