引言
上次博文引用了各连接的示意图,未做详述,本文补充对数据库各连接的实例描述。
举个栗子
数据
数据为klass
与student
的关系,班级一对多学生,没有加外键。
数据关系如下:1
班的Hello Kitty
和史努比,2
班的米老鼠和唐老鸭,3
班没学生,葫芦娃没有班级。
何为连接?
关系型数据库,即数据之间是有所关系的。
就如我们当前场景下的klass
与student
表一样,两表中的数据在实际的业务场景中是有所关联的,学生属于哪个班级,这种多对一的关系,我们在学生表中加上klass_id
一列存储这种关系。
班级与学生的关系通过klass_id
进行维护。
简单的单表查询:
SELECT *
FROM `klass`;
如果想同时看教师和班级的数据,就需要进行多表查询了:
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`, `student`
WHERE `klass`.`id` = `student`.`klass_id`;
How it works?
进行多表查询时,其实是将两表的记录先做笛卡尔积,再根据WHERE
条件对数据进行过滤。
不加WHERE
条件的示例:
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`, `student`;
很惭愧,从我学数据库到现在,每次我手写这样需求的SQL
,都是使用的这种方法进行多表查询。
Better?
试想,如果我们所有的多表查询,都使用WHERE
进行过滤,这会造成一个很严重的问题。
如果查询条件很复杂的话,会导致WHERE
语句不仅充斥着数据表层面的连接条件,还充斥着各种业务条件,会让WHERE
语句很不直观。
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`, `student`
WHERE `klass`.`id` = `student`.`klass_id`;
参考问题:INNER JOIN ON vs WHERE clause - StackOverflow
这种场景下推荐使用内连接代替WHERE
。
内连接可更好地完成上述需求:
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`
INNER JOIN `student`
ON `klass`.`id` = `student`.`klass_id`;
并且,连接的条件写在ON
里,WHERE
只写业务条件,更直观。
左连接/右连接
内连接:内连接基于连接谓词将两张表(如A
和B
)的列组合在一起,产生新的结果表。查询会将A
表的每一行和B
表的每一行进行比较,并找出满足连接谓词的组合。当连接谓词被满足,A
和B
中匹配的行会按列组合(并排组合)成结果集中的一行。
示例数据有三个班,但是3
班因为没有任何学生与之关联,所以不符合查询谓语中的klass.id = student.klass_id
,所以没有3
班的信息。
同样地,因为学生“葫芦娃”没有班级,也不符合查询条件,同样没有出现在内连接的查询 结果中。
注:在表连接中NULL != NULL
如果想让数据显示完全,就需要左连接与右连接了。
klass
表连接student
表,klass
算左表,student
算右表。
左连接,显示左表所有数据:
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`
LEFT JOIN `student`
ON `klass`.`id` = `student`.`klass_id`;
3
班在左连接中出现了:
右连接,显示右表所有数据:
SELECT `klass`.`name` as `klass_name`, `student`.`name` as `student_name`
FROM `klass`
RIGHT JOIN `student`
ON `klass`.`id` = `student`.`klass_id`;
“葫芦娃”在右连接中出现了:
总结
宝剑锋从磨砺出,梅花香自苦寒来。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。