Mysql 表连接查询
Mysql 表连接查询
1、内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符)。包括相等联接和自然联接。
内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。例如,检索 students 和 courses 表中学生标识号相同的所有行。
**
2、外联接。**外联接可以是左向外联接、右向外联接或完整外部联接。
在 FROM 子句中指定外联接时,可以由下列几组关键字中的一组指定:
1)LEFT JOIN 或 LEFT OUTER JOIN
左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
2)RIGHT JOIN 或 RIGHT OUTER JOIN
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
3)FULL JOIN 或 FULL OUTER JOIN
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
**3、交叉联接
**交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉联接也称作笛卡尔积。
FROM 子句中的表或视图可通过内联接或完整外部联接按任意顺序指定;但是,用左或右向外联接指定表或视图时,表或视图的顺序很重要。有关使用左或右向外联接排列表的更多信息,请参见使用外联接。
例子:

1) 内连接

2)左连接

3) 右连接

4) 完全连接

**一、交叉连接(CROSS JOIN)
**交叉连接(CROSS JOIN):有两种,显式的和隐式的,不带 ON 子句,返回的是两表的乘积,也叫笛卡尔积。
例如:下面的语句 1 和语句 2 的结果是相同的。
**语句 1:隐式的交叉连接,没有 CROSS JOIN。
**SELECT O.ID, O.ORDER_NUMBER, C.ID, C.NAME
FROM ORDERS O , CUSTOMERS C
WHERE O.ID=1;
**语句 2:显式的交叉连接,使用 CROSS JOIN。
**SELECT O.ID,O.ORDER_NUMBER,C.ID,
C.NAME
FROM ORDERS O CROSS JOIN CUSTOMERS C
WHERE O.ID=1;
语句 1 和语句 2 的结果是相同的,查询结果如下:
**二、内连接(INNER JOIN)
**内连接(INNER JOIN):有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。(所谓的链接表就是数据库在做查询形成的中间表)。
例如:下面的语句 3 和语句 4 的结果是相同的。
**语句 3:隐式的内连接,没有 INNER JOIN,形成的中间表为两个表的笛卡尔积。
**SELECT O.ID,O.ORDER_NUMBER,C.ID,C.NAME
FROM CUSTOMERS C,ORDERS O
WHERE C.ID=O.CUSTOMER_ID;
**语句 4:显示的内连接,一般称为内连接,有 INNER JOIN,形成的中间表为两个表经过 ON 条件过滤后的笛卡尔积。
**SELECT O.ID,O.ORDER_NUMBER,C.ID,C.NAME
FROM CUSTOMERS C INNER JOIN ORDERS O ON C.ID=O.CUSTOMER_ID;
语句 3 和语句 4 的查询结果:
三、外连接(OUTER JOIN):外连不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。外连接分三类:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。
三者的共同点是都返回符合连接条件和查询条件(即:内连接)的数据行。不同点如下:
左外连接还返回左表中不符合连接条件单符合查询条件的数据行。
右外连接还返回右表中不符合连接条件单符合查询条件的数据行。
全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即 “全外 = 左外 UNION 右外”。
说明:左表就是在 “(LEFT OUTER JOIN)” 关键字左边的表。右表当然就是右边的了。在三种类型的外连接中,OUTER 关键字是可省略的。
下面举例说明:
**语句 5:左外连接(LEFT OUTER JOIN)
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
**语句 6:右外连接(RIGHT OUTER JOIN)
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O RIGHT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
注意:WHERE 条件放在 ON 后面查询的结果是不一样的。例如:
**语句 7:WHERE 条件独立。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
WHERE O.ORDER_NUMBER<>'MIKE_ORDER001';
**语句 8:将语句 7 中的 WHERE 条件放到 ON 后面。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID AND O.ORDER_NUMBER<>'MIKE_ORDER001';
从语句 7 和语句 8 查询的结果来看,显然是不相同的,语句 8 显示的结果是难以理解的。因此,推荐在写连接查询的时候,ON 后面只跟连接条件,而对中间表限制的条件都写到 WHERE 子句中。
**语句 9:全外连接(FULL OUTER JOIN)。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
注意:MySQL 是不支持全外的连接的,这里给出的写法适合 Oracle 和 DB2。但是可以通过左外和右外求合集来获取全外连接的查询结果。下图是上面 SQL 在 Oracle 下执行的结果:
**语句 10:左外和右外的合集,实际上查询结果和语句 9 是相同的。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
UNION
SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O RIGHT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
语句 9 和语句 10 的查询结果是相同的,如下:
四、联合连接(UNION JOIN):这是一种很少见的连接方式。Oracle、MySQL 均不支持,其作用是:找出全外连接和内连接之间差异的所有行。这在数据分析中排错中比较常用。也可以利用数据库的集合操作来实现此功能。
**语句 11:联合查询(UNION JOIN)例句,还没有找到能执行的 SQL 环境。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O UNION JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
**语句 12:语句 11 在 DB2 下的等价实现。还不知道 DB2 是否支持语句 11 呢!
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
EXCEPT
SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O INNER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
**语句 13:语句 11 在 Oracle 下的等价实现。
**SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
MINUS
SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
FROM ORDERS O INNER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
查询结果如下:
五、自然连接(NATURAL INNER JOIN):说真的,这种连接查询没有存在的价值,既然是 SQL2 标准中定义的,就给出个例子看看吧。自然连接无需指定连接列,SQL 会检查两个表中是否相同名称的列,且假设他们在连接条件中使用,并且在连接条件中仅包含一个连接列。不允许使用 ON 语句,不允许指定显示列,显示列只能用 * 表示(ORACLE 环境下测试的)。对于每种连接类型(除了交叉连接外),均可指定 NATURAL。下面给出几个例子。
**语句 14:
**SELECT *
FROM ORDERS O NATURAL INNER JOIN CUSTOMERS C;
**语句 15:
**SELECT *
FROM ORDERS O NATURAL LEFT OUTER JOIN CUSTOMERS C;
**语句 16:
**SELECT *
FROM ORDERS O NATURAL RIGHT OUTER JOIN CUSTOMERS C;
**语句 17:
**SELECT *
FROM ORDERS O NATURAL FULL OUTER JOIN CUSTOMERS C;
六、SQL 查询的基本原理:两种情况介绍。
第一、单表查询:根据 WHERE 条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的);然后根据 SELECT 的选择列选择相应的列进行返回最终结果。
第二、两表连接查询:对两表求积(笛卡尔积)并用 ON 条件和连接连接类型进行过滤形成中间表;然后根据 WHERE 条件过滤中间表的记录,并根据 SELECT 指定的列返回查询结果。
**
第三、**多表连接查询:先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据 WHERE 条件过滤中间表的记录,并根据 SELECT 指定的列返回查询结果。
理解 SQL 查询的过程是进行 SQL 优化的理论依据。
**七、ON 后面的条件(ON 条件)和 WHERE 条件的区别:
**ON 条件:是过滤两个链接表笛卡尔积形成中间表的约束条件。
WHERE 条件:在有 ON 条件的 SELECT 语句中是过滤中间表的约束条件。在没有 ON 的单表查询中,是限制物理表或者中间查询结果返回记录的约束。在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。
从这里可以看出,将 WHERE 条件移入 ON 后面是不恰当的。推荐的做法是:
ON 只进行连接操作,WHERE 只过滤中间表的记录。
**八、总结
**连接查询是 SQL 查询的核心,连接查询的连接类型选择依据实际需求。如果选择不当,非但不能提高查询效率,反而会带来一些逻辑错误或者性能低下。下面总结一下两表连接查询选择方式的依据:
1、 查两表关联列相等的数据用内连接。
2、 Col_L 是 Col_R 的子集时用右外连接。
3、 Col_R 是 Col_L 的子集时用左外连接。
4、 Col_R 和 Col_L 彼此有交集但彼此互不为子集时候用全外。
5、 求差操作的时候用联合查询。
多个表查询的时候,这些不同的连接类型可以写到一块。例如:
SELECT T1.C1,T2.CX,T3.CY
FROM TAB1 T1
INNER JOIN TAB2 T2 ON (T1.C1=T2.C2)
INNER JOIN TAB3 T3 ON (T1.C1=T2.C3)
LEFT OUTER JOIN TAB4 ON(T2.C2=T3.C3);
WHERE T1.X >T3.Y;
上面这个 SQL 查询是多表连接的一个示范。

浙公网安备 33010602011771号