版权声明:本文为自学而写,如有错误还望指出,谢谢^-^ https://blog.csdn.net/weixin_43871369/article/details/89531976
14. 联结表
14.1 联结
联结是利用SQL的select语句能执行的最重要操作
外键:外键是某个表得一列,它包含另一个表的主键值,定义了两个表之间的关系。
14.2 创建联结
mysql> select *from test;
+------+---------+------------------------------------+---------------------+
| t_id | t_name | t_text | t_time |
+------+---------+------------------------------------+---------------------+
| 5 | Tom | This is a cat | 2019-04-25 16:13:39 |
| 4 | Jerry | This is a mouse | 2019-04-25 15:40:55 |
| 6 | Helen | She is a student in middle school. | 2019-04-25 16:13:39 |
| 1 | Helen | NULL | 2019-04-25 16:17:21 |
| 3 | Helen | NULL | 2019-04-25 16:17:21 |
| 7 | Erdison | NULL | 2019-05-04 00:00:00 |
| 8 | Linda | NULL | 2019-04-02 12:00:00 |
| 9 | Lucy | NULL | 2019-05-01 00:00:00 |
| 10 | Tomson | NULL | 0196-04-23 00:00:00 |
+------+---------+------------------------------------+---------------------+
9 rows in set (0.00 sec)
mysql> select * from _test;
+------+--------+---------------------+
| t_id | _name | _time |
+------+--------+---------------------+
| 2 | Linda | 2019-04-02 12:00:00 |
| 3 | Lucy | 2019-05-01 00:00:00 |
| 4 | Tomson | 0196-04-23 00:00:00 |
+------+--------+---------------------+
3 rows in set (0.00 sec)
mysql> select t_name,t_time,_name
-> from test,_test
-> where test.t_id=_test.t_id
-> order by t_name;
+--------+---------------------+--------+
| t_name | t_time | _name |
+--------+---------------------+--------+
| Helen | 2019-04-25 16:17:21 | Lucy |
| Jerry | 2019-04-25 15:40:55 | Tomson |
+--------+---------------------+--------+
2 rows in set (0.00 sec)
务必要加上where语句,不然将会得到两个表的笛卡尔积,检索出来的行数将是第一个表中的行数乘以第二个表中的行数。
mysql> select t_name,t_time,_name
-> from test,_test
-> order by t_name;
+---------+---------------------+--------+
| t_name | t_time | _name |
+---------+---------------------+--------+
| Erdison | 2019-05-04 00:00:00 | Linda |
| Erdison | 2019-05-04 00:00:00 | Lucy |
| Erdison | 2019-05-04 00:00:00 | Tomson |
| Helen | 2019-04-25 16:17:21 | Linda |
| Helen | 2019-04-25 16:13:39 | Lucy |
| Helen | 2019-04-25 16:17:21 | Lucy |
| Helen | 2019-04-25 16:17:21 | Lucy |
| Helen | 2019-04-25 16:13:39 | Tomson |
| Helen | 2019-04-25 16:17:21 | Tomson |
| Helen | 2019-04-25 16:13:39 | Linda |
| Helen | 2019-04-25 16:17:21 | Tomson |
| Helen | 2019-04-25 16:17:21 | Linda |
| Jerry | 2019-04-25 15:40:55 | Tomson |
| Jerry | 2019-04-25 15:40:55 | Linda |
| Jerry | 2019-04-25 15:40:55 | Lucy |
| Linda | 2019-04-02 12:00:00 | Tomson |
| Linda | 2019-04-02 12:00:00 | Linda |
| Linda | 2019-04-02 12:00:00 | Lucy |
| Lucy | 2019-05-01 00:00:00 | Tomson |
| Lucy | 2019-05-01 00:00:00 | Linda |
| Lucy | 2019-05-01 00:00:00 | Lucy |
| Tom | 2019-04-25 16:13:39 | Tomson |
| Tom | 2019-04-25 16:13:39 | Linda |
| Tom | 2019-04-25 16:13:39 | Lucy |
| Tomson | 0196-04-23 00:00:00 | Lucy |
| Tomson | 0196-04-23 00:00:00 | Tomson |
| Tomson | 0196-04-23 00:00:00 | Linda |
+---------+---------------------+--------+
27 rows in set (0.05 sec)
联结的表越多,性能下降的越厉害
14.3 内部联结
目前所用的联结称为等值联结,它基于两个表之间的相等测试。这种联结也称为内部联结。(可以加入inner join...on语句)
mysql> select t_name,t_time,_name
-> from test inner join _test
-> on test.t_id=_test.t_id;
+--------+---------------------+--------+
| t_name | t_time | _name |
+--------+---------------------+--------+
| Helen | 2019-04-25 16:17:21 | Lucy |
| Jerry | 2019-04-25 15:40:55 | Tomson |
+--------+---------------------+--------+
2 rows in set (0.00 sec)
14.4 子查询和联结查询的相似之处
mysql> select t_name,t_time from test
-> where t_id in( select t_id from
-> _test where date(_time) between
-> '0196-04-23' and '2019-04-23');
+--------+---------------------+
| t_name | t_time |
+--------+---------------------+
| Jerry | 2019-04-25 15:40:55 |
+--------+---------------------+
1 row in set (0.06 sec)
mysql> select t_name,t_time
-> from test,_test
-> where test.t_id=_test.t_id
-> and date(_time) between
-> '0196-04-23' and '2019-04-23';
+--------+---------------------+
| t_name | t_time |
+--------+---------------------+
| Jerry | 2019-04-25 15:40:55 |
+--------+---------------------+
1 row in set (0.00 sec)
可以看出子查询和联接查询结果一致,并且联接查询效率较为快一点,因此,对于一种查询往往存在不同的手段,查询效率受操作类型,表中数据量,是否存在索引或键以及其他一些条件的影响。
15. 创建高级联接
15.1 使用表别名
mysql> select t_name,t_time from
-> test as t,_test as _t
-> where t.t_id=_t.t_id
-> and date(_time) between
-> '0196-04-23' and '2019-04-23';
+--------+---------------------+
| t_name | t_time |
+--------+---------------------+
| Jerry | 2019-04-25 15:40:55 |
+--------+---------------------+
1 row in set (0.00 sec)
此例中,表test的别名为t。表别名只用于where子句。但是,表别名不仅能用于where子句,还可以用于select的列表、order by 子句以及语句的其他部分。应该注意的是,表别名只在查询执行中使用,与列别名不一样,表别名不返回客户机。
15.2 使用不同类型的联接
15.21 自联接
首先来看一个子查询例子
mysql> select t_name,t_time from
-> test where t_id in(
-> select t_id from test
-> where date(t_time) between
-> '2019-04-01' and '2019-04-23');
+--------+---------------------+
| t_name | t_time |
+--------+---------------------+
| Linda | 2019-04-02 12:00:00 |
+--------+---------------------+
1 row in set (0.02 sec)
可以将上例转换为相同查询的自联结的形式如下
mysql> select t1.t_name,t1.t_time from
-> test as t1,test as t2
-> where t1.t_id=t2.t_id
-> and date(t2.t_time) between
-> '2019-04-01' and '2019-04-23';
+--------+---------------------+
| t_name | t_time |
+--------+---------------------+
| Linda | 2019-04-02 12:00:00 |
+--------+---------------------+
1 row in set (0.06 sec)
15.22 自然联接
扫描二维码关注公众号,回复:
6070352 查看本文章
无论何时对表进行联结,应该至少有一个列出现不止一个表中(被联结的列)。自然联结就是排出多次出现,使每个列只返回一次。一般通过对表使用通配符(select *),对所有其他表的列使用明确的子集来完成。
mysql> select t.*,_t._name,_t._time
-> from test as t,_test as _t
-> where t.t_id=_t.t_id;
+------+--------+-----------------+---------------------+--------+------------
-------+
| t_id | t_name | t_text | t_time | _name | _time
|
+------+--------+-----------------+---------------------+--------+------------
-------+
| 3 | Helen | NULL | 2019-04-25 16:17:21 | Lucy | 2019-05-01
:00:00 |
| 4 | Jerry | This is a mouse | 2019-04-25 15:40:55 | Tomson | 0196-04-23
:00:00 |
+------+--------+-----------------+---------------------+--------+------------
-------+
2 rows in set (0.00 sec)
迄今为止,我们建立的所有内部联结都是自然连接。
15.23 外部联结
mysql> select test.t_id,_test._name
-> from test left outer join _test
-> on test.t_id=_test.t_id;
+------+--------+
| t_id | _name |
+------+--------+
| 3 | Lucy |
| 4 | Tomson |
| 1 | NULL |
| 5 | NULL |
| 6 | NULL |
| 7 | NULL |
| 8 | NULL |
| 9 | NULL |
| 10 | NULL |
+------+--------+
9 rows in set (0.00 sec)
mysql> select test.t_id,_test._name
-> from test right outer join _test
-> on test.t_id=_test.t_id;
+------+--------+
| t_id | _name |
+------+--------+
| NULL | Linda |
| 3 | Lucy |
| 4 | Tomson |
+------+--------+
3 rows in set (0.00 sec)
从上面两个例子可以看出,left outer join...on和right outer join...on的区别在于left...将会列出from后左边表的所有行,右边表与之不匹配的输出为NULL。right与之相反。
15.3 使用带聚集函数的联结
mysql> select _test.t_id,_test._name,
-> count(test.t_name) as t_cntname
-> from _test inner join test
-> on _test.t_id=test.t_id
-> group by _test.t_id;
+------+--------+-----------+
| t_id | _name | t_cntname |
+------+--------+-----------+
| 3 | Lucy | 1 |
| 4 | Tomson | 1 |
+------+--------+-----------+
2 rows in set (0.06 sec)
mysql> select test.t_id,_test._name,
-> count(test.t_name) as t_cntname
-> from test left outer join _test
-> on test.t_id=_test.t_id
-> group by test.t_id;
+------+--------+-----------+
| t_id | _name | t_cntname |
+------+--------+-----------+
| 1 | NULL | 1 |
| 3 | Lucy | 1 |
| 4 | Tomson | 1 |
| 5 | NULL | 1 |
| 6 | NULL | 1 |
| 7 | NULL | 1 |
| 8 | NULL | 1 |
| 9 | NULL | 1 |
| 10 | NULL | 1 |
+------+--------+-----------+
9 rows in set (0.06 sec)