1、子查询

2、联结表

一、子查询

什么是子查询?

    子查询(subquery),即嵌套在其他查询中的查询。

子查询总是从内向外处理:

    也就是说从最内层的SELECT语句开始执行,然后将返回的记录应用到外层的SELECT查询中。

格式化SQL:

    包含子查询的SELECT语句难以阅读和调试,特别是它们较为复杂时更是如此。把子查询分解为多行并且适当的进行缩进,能极大的简化子查询的使用。

列必须匹配:

    在WHERE 子句中使用子查询,应该保证子查询的SELECT语句具有与外查询的WHERE子句中相同数目的列。

限制与效率:

    对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。通常,子查询将返回单个列并且与单个列匹配。但是如果又需要也可以使用多个列。

    虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、不等于(!=)。但是我们必须注意,使用的操作符与子查询返回的记录数需要对应。子查询最常见的使用是在WHERE子句的IN操作符中,因为我们无法保证子查询返回的结果集数目。

如何编写子查询:

    逐渐增加子查询来建立查询:首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。然后重复这些步骤。



二、连接表

    SQL最强大的功能之一就是能在数据检索查询的执行中联结(join)表。联结是利用SQL的SELECT能执行的最重要的操作,很好的理解联结及其语法是学习SQL的一个极为重要的组成部分。

MySQL入门-10:子查询与联结表_第1张图片

为什么要使用联接表?

    如果数据存储在多个表中,怎样用单条SELECT语句检索出数据?答案是使用联结。简单的说,联结是一种机制,用来在一条SELECT语句中关联表,因此称之为联结。

完全限定列名:

    在引用的列可能出现二义性时,必须使用完全限定列名。

维护引用完整性:

    重要的是,要理解联结不是物理实体。它在实际的数据库表中不存在,联结由MySQL根据需要建立,它存在于查询的的执行当中。

    通过主键和外键来建立表之间的联系。维护表间的引用完整性。外键就相当于一个指针,指向另一个表中的主键。

WHERE子句的重要性:

    SELECT语句中联结几个表时,相应的关系是在运行中构造的。在数据库表的定义中,不存在能指示MySQL如何对表进行联结的东西。必须自己做这件事情。在联结两个表时,你实际上做的是将第一个表中的每一行与第二个表中的每一行配对。然后WHERE子句作为过滤条件,过滤出只包含那些匹配给定条件(联结条件)的行。


连接的原理:产生笛卡尔积,然后利用条件去过滤不需要的行。


笛卡尔积:

没有联结条件的表关系返回的结果为笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。


联结的两种形式:

WHERE:使用简单(个人比较倾向于这种方式)

JOIN:ANSI SQL规范首选JOIN语法,这种方式更加明确。

join
将2个或者多个表以一定的连接条件连接起来,从中检索出满足条件的数据

select .. from a,b
由于a,b表之间没有指定连接条件,将产生笛卡尔积(列=a + b, 行=a * b),表将急剧增大

select .. from a,b where ...
产生笛卡尔积,然后利用条件进行过滤

select .. from a,b where a.id = b.id
首先产生笛卡尔积,然后再把满足 a.id = b.id 的行过滤出来(列 = a +b)

select .. from a join b on 1=1
产生笛卡尔积,因为条件 1=1 永远为true,相当于没有指定连接条件
-- join   on  连接条件, 有join 就必须有 on 
当a, b 存在同样的字段,必须要加前缀 a.colome , b.colome

select .. from a join b on a.id = b.id
与
select .. from a,b where a.id = b.id
等价
但是,当结合多个表(超过3个)的时候,join更清晰,而且是SQL标准

 

使用表别名:

  • 缩短SQL语句

  • 允许在单条SELECT语句中多次使用相同的表。

注意:表别名只在查询执行中使用。与列别名不一样,表别名并不返回到结果中去,表别名不返回到客户机。

 

联结多个表:

    SQL对一条SELECT语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。首先列出所有表,然后定义表之间的关系,也就是说定义根据什么条件进行联结。

性能考虑:不要联结不必要的表,联结的表越多,性能下降越厉害。


创建高级联结


自联结

使用表别名的主要原因之一是能在单条SELECT语句中不止一次引用相同的表。那么表别名也为自联结创造了条件,自联结:顾名思义,也就是表自己联结自己。

 
车站表:
  stops(id, name)

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

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

SELECT * FROM route R1, route R2 WHERE R1.num=R2.num AND R1.company=R2.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’


自然联结

无论何时对表进行联结,应该至少有一个列出现在不止一个表中。标准的联结返回所有数据,甚至相同的列多次出现。自然联结排除多次出现,使每个列只返回一次。

 

内部联结, 等值联接

也称为等值联结(equl join),它基于两个表之间的相等测试。不管限制条件在on还是在where中,内连接都得到笛卡尔积中满足所有条件的记录。

INNER JOIN .. ON
与 where 等价

外部联结

LEFT OUTER JOIN .. ON            -- 从左表返回所有行
RIGHT OUTER JOIN .. ON           -- 从右表返回所有行

  存在两种基本的外部联结形式:左外部联结和右外部联结。它们之间的唯一差别是所关联的表的顺序不同。


使用联结和联结条件

  • 注意所使用的联结类型

  • 保证使用正确的联结条件,否则将返回不正确的数据

  • 应该总是提供联结条件,否则会得到笛卡儿积

  • 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。