1.表连接
//>>> Ⅰ.不同数据表之间的连接
(1)内连接(inner join)
内连接组合两张表,并且基于两张表中的关联关系来连接它们。使用内连接需要指定表中哪些字段组成关联关系,并且需要指定基于什么条件进行连接。
内连接要求组成连接的两个表必须具有匹配的记录。(无法匹配NULL值的记录)
语法:
inner join table_name
on condition ;
举例: 检索所有的客户姓名为mike的客户的订单号及价格
SELECT FNumber ,FPrice FROM t_order
INNER JOIN t_customer
ON FCustomerId=t_customer.FId
WHERE t_customer.FName='mike';
注意:
在大多数数据库系统中,inner join 中的inner是可选的。inner join是默认的连接方式
为了避免列名的歧义,建议使用表连接的时候要显示字段所属的表。
(2)不等值连接
处理等值连接,还存在另一种不等值连接。在连接的条件中可以使用小于,大于,不等于等运算符,而且可以使用Like ,between and 等运算符,甚至可以使用函数。
如:需要检索价格小于每个客户年龄的5倍值的订单列表,那么就可以使用不等值连接:
SELECT t_order.`FNumber`,t_order.`FPrice`,t_order.`FCustomerId`
,t_customer.`FName`,t_customer.`FAge`
FROM t_order
NNER JOIN t_customer
ON t_order.`FPrice`<t_customer.`FAge`*5;
//>>>说明:
不等值连接产生大量的查询结果,因为它是对被连接的两张表做笛卡尔积运算。
//>>>解决方案:
如果想查看客户对应的订单,那么就要在不等值连接后添加等值连接匹配条件
SELECT t_order.`FNumber`,t_order.`FPrice`,t_order.`FCustomerId`
,t_customer.`FName`,t_customer.`FAge`
FROM t_order
NNER JOIN t_customer
ON t_order.`FPrice`<t_customer.`FAge`*5
AND t_order.`FCustomerId`=t_customer.`FId`;---等值连接匹配条件清除重复
(3)交叉连接
与内连接比起来,交叉连接非常简单。因为它不存在on子句。
交叉连接会将涉及到的所有表中的所有记录都包含在结果集中。
1.隐式方式定义交叉连接 --->>只要在select 语句中的from语句后将要进行交叉连接的表名列出即可。(可以使用表的别名)
举例:将t_customer表和t_order表做交叉连接
SELECT * FROM t_order , t_customer
2.显示方式定义交叉连接--->>>使用cross join 关键字,语法类似inner join
SELECT t_order.`FNumber`,t_order.`FPrice`,t_order.`FCustomerId`
,t_customer.`FName`,t_customer.`FAge`
FROM t_order
CROSS JOIN t_customer
注意: cross join的声明方式只能被mysql ,MSSQLServer ,oracle所支持,db2不支持。
但隐式交叉连接所有数据库都支持。
(4)自连接 //>>>Ⅱ.同一张表直接的连接
自连接不是独立于前几种连接方式的。它只是那几种连接方式中的一种特例。也就是说,交叉连接,内连接,不等值连接用在同一张表就称为自连接。
举例:需要检索与另外一个订单的订单类型一样的所有订单的列表。
错误写法1:
SELECT FNumber ,FPrice ,FTypeId
FROM t_order
WHERE FTypeId=FTypeId;
错误分析:这里where语句条件永远为真,因为同行的相同列总是等于自己。因此结果集中将包含表中的所有记录。
解决方案: 假象存在另一个t_order表与t_order表完全相同的表,然后我们就可以在这两张表中进行任意的连接了。(需区分这两张表,使用表的别名)
//这里使用inner join进行连接如下: --->>>仍然存在一点问题???
SELECT o1.FNumber ,o1.FPrice ,o1.FTypeId,
o2.FNumber ,o2.FPrice ,o2.FTypeId
FROM t_order o1
INNER JOIN t_order o2
ON o1.FTypeId=o2.FTypeId;
//为t_order表取了两个别名o1,o2;
问题:存在‘A匹配B,B匹配A’的问题。如自己与自己的订单类型必定相同
解决方案:我们这里真正要查询的是具有相同的FTypedId字段值的两个不同的订单,因此需加个条件:and o1.FId=o2.FId;
最终正确的sql语句是:
SELECT o1.FNumber ,o1.FPrice ,o1.FTypeId,
o2.FNumber AS O2_FNumber ,o2.FPrice AS O2_FPrice ,o2.FTypeId AS o2_FTypeId
FROM t_order o1
INNER JOIN t_order o2
ON o1.FTypeId=o2.FTypeId
AND o1.FId<>o2.FId;
(5)外部连接--->主要用来解决空值匹配问题
语法与内部连接几乎一致,主要区别就是对空值的处理。。外部连接不需要两个表具有匹配记录,这样就可以指定给某个表中的记录总是放到结果集中。
根据哪个表的记录总是放在结果集中,外部连接分为三种类型:
类型一:右外部连接(RIGHT OUTER JOIN)
类型二:左外部连接(LEFT OUTER JOIN)
类型三:全外连接(FULL OUTER JOIN)
三者共同点: 都返回符合连接条件的数据,这一点和内部连接是一样的。
不同点:
◆左外部连接还返回左表中不符合条件是数据
◆右外部连接还返回右表中不符合条件是数据
◆全外部连接将返回左表中和右表中不符合条件的数据,是左外部连接和右外部连接的集合。
注意:这里的左表右表是相对join关键字来说的,在join关键字左侧的称为左表,右侧称为右表。
如:
SELECT o1.FNumber ,o1.FPrice ,o1.FTypeId,
o2.FNumber AS O2_FNumber ,o2.FPrice AS O2_FPrice ,o2.FTypeId AS o2_FTypeId
FROM t_order o1
INNER JOIN t_order o2
ON o1.FTypeId=o2.FTypeId
AND o1.FId<>o2.FId;
左表:o1
右表:o2