1、子查询
2、联结表
一、子查询
什么是子查询?
子查询(subquery),即嵌套在其他查询中的查询。
子查询总是从内向外处理:
也就是说从最内层的SELECT语句开始执行,然后将返回的记录应用到外层的SELECT查询中。
格式化SQL:
包含子查询的SELECT语句难以阅读和调试,特别是它们较为复杂时更是如此。把子查询分解为多行并且适当的进行缩进,能极大的简化子查询的使用。
列必须匹配:
在WHERE 子句中使用子查询,应该保证子查询的SELECT语句具有与外查询的WHERE子句中相同数目的列。
限制与效率:
对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。通常,子查询将返回单个列并且与单个列匹配。但是如果又需要也可以使用多个列。
虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、不等于(!=)。但是我们必须注意,使用的操作符与子查询返回的记录数需要对应。子查询最常见的使用是在WHERE子句的IN操作符中,因为我们无法保证子查询返回的结果集数目。
如何编写子查询:
逐渐增加子查询来建立查询:首先,建立和测试最内层的查询。然后,用硬编码数据建立和测试外层查询,并且仅在确认它正常后才嵌入子查询。然后重复这些步骤。
二、连接表
SQL最强大的功能之一就是能在数据检索查询的执行中联结(join)表。联结是利用SQL的SELECT能执行的最重要的操作,很好的理解联结及其语法是学习SQL的一个极为重要的组成部分。
为什么要使用联接表?
如果数据存储在多个表中,怎样用单条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 -- 从右表返回所有行
存在两种基本的外部联结形式:左外部联结和右外部联结。它们之间的唯一差别是所关联的表的顺序不同。
使用联结和联结条件
注意所使用的联结类型
保证使用正确的联结条件,否则将返回不正确的数据
应该总是提供联结条件,否则会得到笛卡儿积
在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。