zoukankan      html  css  js  c++  java
  • MySQL的Join使用

    在MySQL(以5.1为例)中,表连接的语法可以参见MySQL官方手册:MySQL官方手册-JOIN

    在查询中,连接的语法类似

    1. SELECT select_expr FROM table_references  


    table_references(对表的引用)的定义如下(也可以看成连接表达式):(晕晕晕哈)

    1. table_references:  
    2.     table_reference [, table_reference] ...  
    3.   
    4. table_reference:  
    5.     table_factor  
    6.   | join_table  
    7.   
    8. table_factor:  
    9.     tbl_name [[AS] alias] [index_hint_list]  
    10.   | table_subquery [AS] alias  
    11.   | ( table_references )  
    12.   | { OJ table_reference LEFT OUTER JOIN table_reference  
    13.         ON conditional_expr }  
    14.   
    15. join_table:  
    16.     table_reference [INNER | CROSS] JOIN table_factor [join_condition]  
    17.   | table_reference STRAIGHT_JOIN table_factor  
    18.   | table_reference STRAIGHT_JOIN table_factor ON conditional_expr  
    19.   | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition  
    20.   | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor  
    21.   
    22. join_condition:  
    23.     ON conditional_expr  
    24.   | USING (column_list)  
    25.   
    26. index_hint_list:  
    27.     index_hint [, index_hint] ...  
    28.   
    29. index_hint:  
    30.     USE {INDEX|KEY}  
    31.       [{FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])  
    32.   | IGNORE {INDEX|KEY}  
    33.       [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)  
    34.   | FORCE {INDEX|KEY}  
    35.       [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)  
    36.   
    37. index_list:  
    38.     index_name [, index_name] ...  


    其中,table_factor是基本的表选择,而join_table是基于表的一些扩展。
    下面,通过实验介绍一下表连接。
    首先,假设有以下几个表

    table1
    book
    1 java
    2 c++
    3 php


    table2
    author
    2 zhang
    3 wang
    4 li


    table3
    year
    zhang 2003
    ma 2006
    liu 2011

    Inner Join 内连接
    将两个表中存在连接关系的字段,组成的记录集,叫做内连接。
    内连接等价于

    1. mysql> select table1.id as id,book,author from table1, table2 where table1.id=table2.id;  
    2. +------+------+--------+  
    3. | id   | book | author |  
    4. +------+------+--------+  
    5. |    2 | c++  | zhang  |  
    6. |    3 | php  | wang   |  
    7. +------+------+--------+  
    8. rows in set (0.00 sec)  
    9. mysql> select * from table1 inner join table2 using (id);  
    10. +------+------+--------+  
    11. | id   | book | author |  
    12. +------+------+--------+  
    13. |    2 | c++  | zhang  |  
    14. |    3 | php  | wang   |  
    15. +------+------+--------+  
    16. rows in set (0.00 sec)  


    可以看出,两者是等价的。没有Using子句的Inner Join相当于是求两个table的笛卡尔积。
    Cross Join 交叉连接
    在Mysql中,Cross Join可以用逗号表达式表示,例如(table1, table 2)。在Mysql中,Cross Join 和 Inner Join 是等价的,但是在标准SQL中,它们并不等价,Inner Join 用于带有on表达式的连接,反之用Cross Join。以下两个SQL语句是等价的。
    Cross Join 指的是两个table的笛卡尔积。以下三句SQL是等价的。

    1. mysql> select * from table1 inner join table2;  
    2. mysql> select * from table1 cross join table2;  
    3. mysql> select * from (table1, table2);  
    4. mysql> select * from table1 nature join table2;  
    5. 结果集:  
    6. +------+------+------+--------+  
    7. | id   | book | id   | author |  
    8. +------+------+------+--------+  
    9. |    1 | java |    2 | zhang  |  
    10. |    2 | c++  |    2 | zhang  |  
    11. |    3 | php  |    2 | zhang  |  
    12. |    1 | java |    3 | wang   |  
    13. |    2 | c++  |    3 | wang   |  
    14. |    3 | php  |    3 | wang   |  
    15. |    1 | java |    4 | li     |  
    16. |    2 | c++  |    4 | li     |  
    17. |    3 | php  |    4 | li     |  
    18. +------+------+------+--------+  


    不难理解,下面两句SQL也是等价的。

    1. mysql> select * from table1 left join (table2, table3) on (table2.id = table1.id and table2.author = table3.author);  
    2. mysql> select * from table1 left join (table2 cross join table3) on (table2.id = table1.id and table2.author = table3.author);  
    3. 结果集:  
    4. +------+------+------+--------+--------+------+  
    5. | id   | book | id   | author | author | year |  
    6. +------+------+------+--------+--------+------+  
    7. |    1 | java | NULL | NULL   | NULL   | NULL |  
    8. |    2 | c++  |    2 | zhang  | zhang  | 2003 |  
    9. |    3 | php  | NULL | NULL   | NULL   | NULL |  
    10. +------+------+------+--------+--------+------+  


    Natural Join 自然连接
    NATURAL [LEFT] JOIN:这个句子的作用相当于INNER JOIN,或者是在USING子句中包含了联结的表中所有公共字段的Left JOIN(左联结)。
    也就是说:下面两个SQL是等价的。

    1. mysql> select * from table1 natural join table2;  
    2. mysql> select * from table1 inner join table2 using (id);  
    3.   
    4. 结果集:  
    5. +------+------+--------+  
    6. | id   | book | author |  
    7. +------+------+--------+  
    8. |    2 | c++  | zhang  |  
    9. |    3 | php  | wang   |  
    10. +------+------+--------+  


    同时,下面两个SQL也是等价的。

    1. mysql> select * from table1 natural left join table2;  
    2. mysql> select * from table1 left join table2 using(id);  
    3. 结果集:  
    4. +------+------+--------+  
    5. | id   | book | author |  
    6. +------+------+--------+  
    7. |    1 | java | NULL   |  
    8. |    2 | c++  | zhang  |  
    9. |    3 | php  | wang   |  
    10. +------+------+--------+  


    Left Join 左外连接
    左外连接A、B表的意思就是将表A中的全部记录和表B中字段连接形成的记录集,这里注意的是最后出来的记录集会包括表A的全部记录。
    左连接表1,表二等价于右连接表二,表一。如下两个SQL是等价的:

    1. mysql> select * from table1 left join table2 using (id);  
    2. mysql> select * from table2 right join table1 using (id);  
    3. 结果集:  
    4. +------+------+--------+  
    5. | id   | book | author |  
    6. +------+------+--------+  
    7. |    1 | java | NULL   |  
    8. |    2 | c++  | zhang  |  
    9. |    3 | php  | wang   |  
    10. +------+------+--------+  


    Right Join 右外连接

    右外连接和左外连接是类似的。为了方便数据库便于访问,推荐使用左外连接代替右外连接。


    最后,讲一下Mysql表连接的一些注意事项。

    1、两个表求差集的方法
    如果求 左表 - 右表 的差集,使用类似下面的SQL:

    1. SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;  
    2. 例如  
    3. mysql> select table1.* from table1 left join table2 using(id) where table2.id is null;  
    4. +------+------+  
    5. | id   | book |  
    6. +------+------+  
    7. |    1 | java |  
    8. +------+------+  
    9. 1 row in set (0.00 sec)  


    2、Using子句
    Using子句可以使用On子句重写。但是使用Select * 查询出的结果有差别。以下两句话是等价的:

    1. mysql> select id, book, author from table1 join table2 using (id);  
    2. mysql> select table1.id, book, author from table1 join table2 on table1.id=table2.id;  
    3. 结果集:  
    4. +------+------+--------+  
    5. | id   | book | author |  
    6. +------+------+--------+  
    7. |    2 | c++  | zhang  |  
    8. |    3 | php  | wang   |  
    9. +------+------+--------+  


    但是下面两个有些许不同,使用on时候,重复的部分会被输出两次。

    1. mysql> select * from table1 join table2 using (id);  
    2. +------+------+--------+  
    3. | id   | book | author |  
    4. +------+------+--------+  
    5. |    2 | c++  | zhang  |  
    6. |    3 | php  | wang   |  
    7. +------+------+--------+  
    8. rows in set (0.00 sec)  
    9. mysql> select * from table1 join table2 on table1.id=table2.id;  
    10. +------+------+------+--------+  
    11. | id   | book | id   | author |  
    12. +------+------+------+--------+  
    13. |    2 | c++  |    2 | zhang  |  
    14. |    3 | php  |    3 | wang   |  
    15. +------+------+------+--------+  
    16. rows in set (0.00 sec)  


    3、Straight Join的使用
    STRAIGHT_JOIN 和 JOIN相似,除了大部分情况下,在使用STRAIGHT_JOIN时候,先读右表后读左表。而在大部分情况下是先读左表的。STRAIGHT_JOIN仅用于少数情况下的表连接性能优化,比如右表记录数目明显少于左表。

    4、Mysql表连接的运算顺序
    在MySQL 5.1版本中,INNER JOIN, CROSS JOIN, LEFT JOIN, 和RIGHT JOIN 比逗号表达式具有更高的优先级。
    因此SQL1被解析成SQL3,而不是SQL2。

    1. SQL1 : SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);  
    2. SQL2 : SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);  
    3. SQL3 : SELECT * FROM t1, (t2 JOIN t3 ON (t1.i1 = t3.i3));  


    因此会报错,找不到i1列。因此以后在写这样的查询的时候,最好写明白,不要省略括号,这样能避免很多错误。

    5、循环的自然连接
    在MySQL 5.1版本中,SQL1等价于SQL3, 而在MySQL以前版本中,SQL1等价于SQL2。

      1. SQL1 : SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;  
      2. SQL2 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c;  
      3. SQL3 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a; 
  • 相关阅读:
    centos环境无法安装paramiko的问题解决
    openstack swift节点安装手册3-最后的安装配置及验证
    P4329 [COCI2006-2007#1] Bond
    P4802 [CCO 2015]路短最
    树链剖分(从入门到入土。)
    分块详解
    Cocos2d-x 详解坐标系统
    pureMVC介绍及学习
    pureMVC简单示例及其原理讲解五(Facade)
    pureMVC简单示例及其原理讲解四(Controller层)
  • 原文地址:https://www.cnblogs.com/subtract/p/3880743.html
Copyright © 2011-2022 走看看