Mysql从入门到入魔——6. 表联结、组合查询

x33g5p2x  于2021-12-19 转载在 其他  
字(4.2k)|赞(0)|评价(0)|浏览(440)

本篇主要内容

自联结、等值联结、内联结、自然联结、外联结及对比图,UNION组合查询。如果对文中表结构不理解的可以查看系列首页。话不多说,进入正题!

1. 表联结

联结是一种机制,用来在一条 SELECT 语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。联结不是物理实体。换句话说,它在实际的数据库表中并不存在。它只在查询执行期间存在。

1.1 自联结

假如要给与顾客联系名为 Jim Jones 的同一公司的所有顾客发送一封信件。这个查询要求首先找出 Jim Jones 工作的公司名,然后找出在该公司工作的顾客。下面使用子查询和自联结分别实现。

先看一下子查询的方式:

  1. mysql> SELECT cust_id, cust_name, cust_contact
  2. -> FROM Customers
  3. -> WHERE cust_name = (SELECT cust_name
  4. -> FROM Customers
  5. -> WHERE cust_contact = 'Jim Jones');
  6. +------------+-----------+--------------------+
  7. | cust_id | cust_name | cust_contact |
  8. +------------+-----------+--------------------+
  9. | 1000000003 | Fun4All | Jim Jones |
  10. | 1000000004 | Fun4All | Denise L. Stephens |
  11. +------------+-----------+--------------------+

接下来使用自联结的方式:

  1. mysql> SELECT c1.cust_id, c1.cust_name, c1.cust_contact
  2. -> FROM Customers AS c1, Customers AS c2
  3. -> WHERE c1.cust_name = c2.cust_name
  4. -> AND c2.cust_contact = 'Jim Jones';
  5. +------------+-----------+--------------------+
  6. | cust_id | cust_name | cust_contact |
  7. +------------+-----------+--------------------+
  8. | 1000000003 | Fun4All | Jim Jones |
  9. | 1000000004 | Fun4All | Denise L. Stephens |
  10. +------------+-----------+--------------------+

通常情况下,自联结的方式比子查询的方式要快很多。

1.2 等值联结

为了各种联结的对比效果更佳,下面的示例均使用以下 table1table2 表中的数据。
两表 table1table2 中数据如下:

  1. table1 table2
  2. +------+------+------+ +------+------+------+
  3. | A | B | C | | C | D | E |
  4. +------+------+------+ +------+------+------+
  5. | 1 | 2 | 3 | | 2 | 3 | 4 |
  6. | 4 | 5 | 6 | | 6 | 7 | 8 |
  7. +------+------+------+ +------+------+------+

现在通过等值联结,获取两个表中的数据。

  1. mysql> SELECT *
  2. -> FROM table1 AS t1, table2 AS t2
  3. -> WHERE t1.C = t2.C;
  4. +------+------+------+------+------+------+
  5. | A | B | C | C | D | E |
  6. +------+------+------+------+------+------+
  7. | 4 | 5 | 6 | 6 | 7 | 8 |
  8. +------+------+------+------+------+------+

注意:上例中WHERE 中限制了联结条件,如果没有条件的话,返回的结果就是两表的笛卡尔积,返回 6 × 9 共 54 条数据

1.3 内联结

上面的联结也可以称为内联结,它还有另一种语法。返回的结果以上面相同。

  1. mysql> SELECT *
  2. -> FROM table1 AS t1 INNER JOIN table2 AS t2
  3. -> ON t1.C = t2.C;
  4. +------+------+------+------+------+------+
  5. | A | B | C | C | D | E |
  6. +------+------+------+------+------+------+
  7. | 4 | 5 | 6 | 6 | 7 | 8 |
  8. +------+------+------+------+------+------+

1.4 自然联结

自然连接是一种特殊的等值连接,它在两个关系表中自动比较相同的属性列,无须添加连接条件,并且在结果中消除重复的属性列。

  1. mysql> SELECT *
  2. -> FROM table1 AS t1 NATURAL JOIN table2 t2;
  3. +------+------+------+------+------+
  4. | C | A | B | D | E |
  5. +------+------+------+------+------+
  6. | 6 | 4 | 5 | 7 | 8 |
  7. +------+------+------+------+------+

1.5 外联结

1.5.1 左外联结

左外联结,左表( table1 )的记录将会全部表示出来,而右表( table2 )只会显示符合搜索条件的记录。右表记录不足的地方均为 NULL

  1. mysql> SELECT *
  2. -> FROM table1 AS t1 LEFT JOIN table2 AS t2
  3. -> ON t1.C = t2.C;
  4. +------+------+------+------+------+------+
  5. | A | B | C | C | D | E |
  6. +------+------+------+------+------+------+
  7. | 4 | 5 | 6 | 6 | 7 | 8 |
  8. | 1 | 2 | 3 | NULL | NULL | NULL |
  9. +------+------+------+------+------+------+

1.5.1 右外联结

右外联结,右表( table2 )的记录将会全部表示出来,而左表( table1 )只会显示符合搜索条件的记录。左表记录不足的地方均为 NULL

  1. mysql> SELECT *
  2. -> FROM table1 AS t1 RIGHT JOIN table2 AS t2
  3. -> ON t1.C = t2.C;
  4. +------+------+------+------+------+------+
  5. | A | B | C | C | D | E |
  6. +------+------+------+------+------+------+
  7. | 4 | 5 | 6 | 6 | 7 | 8 |
  8. | NULL | NULL | NULL | 2 | 3 | 4 |
  9. +------+------+------+------+------+------+

1.6 四种联结对比图

|

内联结 |

自然联结(去重) |
|

左外联结 |

右外联结 |

2. 组合查询

2.1 UNION组合查询

假如需要 IllinoisIndianaMichigan 等几个州的所有顾客的报表,还想包括不管位于哪个州的所有 Fun4All 公司的顾客。

  1. mysql> SELECT cust_name, cust_contact, cust_email
  2. -> FROM Customers
  3. -> WHERE cust_state IN ('IL', 'IN', 'MI')
  4. -> UNION
  5. -> SELECT cust_name, cust_contact, cust_email
  6. -> FROM Customers
  7. -> WHERE cust_name = 'Fun4All';
  8. +---------------+--------------------+-----------------------+
  9. | cust_name | cust_contact | cust_email |
  10. +---------------+--------------------+-----------------------+
  11. | Village Toys | John Smith | sales@villagetoys.com |
  12. | Fun4All | Jim Jones | jjones@fun4all.com |
  13. | The Toy Store | Kim Howard | NULL |
  14. | Fun4All | Denise L. Stephens | dstephens@fun4all.com |
  15. +---------------+--------------------+-----------------------+

UNION 默认去重,单独执行两个子查询的结果相加应该有 5 行。

如果实际情况不需要去重,可以使用 UNION ALL 来实现。

  1. mysql> SELECT cust_name, cust_contact, cust_email
  2. -> FROM Customers
  3. -> WHERE cust_state IN ('IL', 'IN', 'MI')
  4. -> UNION ALL
  5. -> SELECT cust_name, cust_contact, cust_email
  6. -> FROM Customers
  7. -> WHERE cust_name = 'Fun4All';
  8. +---------------+--------------------+-----------------------+
  9. | cust_name | cust_contact | cust_email |
  10. +---------------+--------------------+-----------------------+
  11. | Village Toys | John Smith | sales@villagetoys.com |
  12. | Fun4All | Jim Jones | jjones@fun4all.com |
  13. | The Toy Store | Kim Howard | NULL |
  14. | Fun4All | Jim Jones | jjones@fun4all.com |
  15. | Fun4All | Denise L. Stephens | dstephens@fun4all.com |
  16. +---------------+--------------------+-----------------------+

相关文章