数据库连接查询总结
建表SQL
create table account ( account_id bigint PRIMARY KEY AUTO_INCREMENT, name varchar(64) ); create table id_num ( id bigint PRIMARY KEY AUTO_INCREMENT, account_id bigint, id_num varchar(64) ); INSERT INTO account
(account_id
, name
) VALUES (1, '张宇'), (2, '王龙飞'), (3, '聂海生'), (4, '陈同贵'), (5, '宋立嘉'), (11, '郑天民'), (12, '王显平'); INSERT INTO id_num
(id
, account_id
, id_num
) VALUES (1, 1, '370205621219253'), (2, 2, '370206501122483'), (3, 3, '370203640507092'), (4, 4, '370206520713161'), (5, 5, '370205551013054'), (6, 5, '370206650615081'), (21, 21, '370206340306481'), (22, 22, '370727770614713');
基础数据
用户表,共7条数据:
select * from account;
account_id | name |
---|---|
1 | 张宇 |
2 | 王龙飞 |
3 | 聂海生 |
4 | 陈同贵 |
5 | 宋立嘉 |
11 | 郑天民 |
12 | 王显平 |
身份证表,共8条数据:
select * from id_num;
id | account_id | id_num |
---|---|---|
1 | 1 | 370205621219253 |
2 | 2 | 370206501122483 |
3 | 3 | 370203640507092 |
4 | 4 | 370206520713161 |
5 | 5 | 370205551013054 |
6 | 5 | 370206650615081 |
21 | 21 | 370206340306481 |
22 | 22 | 370727770614713 |
分析数据:
用户1~4都拥有1个身份证号,用户5拥有2个身份证号码,用户11、12没有登记身份证号码;
身份证21、22没有对应用户。
以下示例都在MySQL中进行了执行及验证,确保结果正确。
笛卡尔积:****cross join
select * from account cross join id_num;
select * from account join id_num;
account_id | name | id | account_id | id_num |
---|---|---|---|---|
1 | 张宇 | 1 | 1 | 370205621219253 |
2 | 王龙飞 | 1 | 1 | 370205621219253 |
3 | 聂海生 | 1 | 1 | 370205621219253 |
4 | 陈同贵 | 1 | 1 | 370205621219253 |
5 | 宋立嘉 | 1 | 1 | 370205621219253 |
11 | 郑天民 | 1 | 1 | 370205621219253 |
12 | 王显平 | 1 | 1 | 370205621219253 |
1 | 张宇 | 2 | 2 | 370206501122483 |
2 | 王龙飞 | 2 | 2 | 370206501122483 |
3 | 聂海生 | 2 | 2 | 370206501122483 |
4 | 陈同贵 | 2 | 2 | 370206501122483 |
5 | 宋立嘉 | 2 | 2 | 370206501122483 |
11 | 郑天民 | 2 | 2 | 370206501122483 |
12 | 王显平 | 2 | 2 | 370206501122483 |
1 | 张宇 | 3 | 3 | 370203640507092 |
2 | 王龙飞 | 3 | 3 | 370203640507092 |
3 | 聂海生 | 3 | 3 | 370203640507092 |
4 | 陈同贵 | 3 | 3 | 370203640507092 |
5 | 宋立嘉 | 3 | 3 | 370203640507092 |
11 | 郑天民 | 3 | 3 | 370203640507092 |
12 | 王显平 | 3 | 3 | 370203640507092 |
1 | 张宇 | 4 | 4 | 370206520713161 |
2 | 王龙飞 | 4 | 4 | 370206520713161 |
3 | 聂海生 | 4 | 4 | 370206520713161 |
4 | 陈同贵 | 4 | 4 | 370206520713161 |
5 | 宋立嘉 | 4 | 4 | 370206520713161 |
11 | 郑天民 | 4 | 4 | 370206520713161 |
12 | 王显平 | 4 | 4 | 370206520713161 |
1 | 张宇 | 5 | 5 | 370205551013054 |
2 | 王龙飞 | 5 | 5 | 370205551013054 |
3 | 聂海生 | 5 | 5 | 370205551013054 |
4 | 陈同贵 | 5 | 5 | 370205551013054 |
5 | 宋立嘉 | 5 | 5 | 370205551013054 |
11 | 郑天民 | 5 | 5 | 370205551013054 |
12 | 王显平 | 5 | 5 | 370205551013054 |
1 | 张宇 | 6 | 5 | 370206650615081 |
2 | 王龙飞 | 6 | 5 | 370206650615081 |
3 | 聂海生 | 6 | 5 | 370206650615081 |
4 | 陈同贵 | 6 | 5 | 370206650615081 |
5 | 宋立嘉 | 6 | 5 | 370206650615081 |
11 | 郑天民 | 6 | 5 | 370206650615081 |
12 | 王显平 | 6 | 5 | 370206650615081 |
1 | 张宇 | 21 | 21 | 370206340306481 |
2 | 王龙飞 | 21 | 21 | 370206340306481 |
3 | 聂海生 | 21 | 21 | 370206340306481 |
4 | 陈同贵 | 21 | 21 | 370206340306481 |
5 | 宋立嘉 | 21 | 21 | 370206340306481 |
11 | 郑天民 | 21 | 21 | 370206340306481 |
12 | 王显平 | 21 | 21 | 370206340306481 |
1 | 张宇 | 22 | 22 | 370727770614713 |
2 | 王龙飞 | 22 | 22 | 370727770614713 |
3 | 聂海生 | 22 | 22 | 370727770614713 |
4 | 陈同贵 | 22 | 22 | 370727770614713 |
5 | 宋立嘉 | 22 | 22 | 370727770614713 |
11 | 郑天民 | 22 | 22 | 370727770614713 |
12 | 王显平 | 22 | 22 | 370727770614713 |
笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个知对象是Y的所有可能有序对的其中一个成员。
直观的说就是集合A{a1,a2,a3} 集合B{b1,b2},他们的笛卡尔积 是 A*B ={(a1,b1),(a1,b2),(a2,b1),(a2,b2),(a3,b1),(a3,b2)}任意两个元素道结合在一起。
笛卡尔积存在的意义是什么?
虽然”笛卡尔积“在实际问题中很少会用到,但”笛卡尔积“不仅仅存在数学意义,也存在现实意义的,比如集合A是一个班的学生,集合B是所有的选修课,A与B的笛卡尔积,表示了学生选择课程的所有可能性
自然连接:natural join
select * from account natural join id_num;
account_id | name | id | id_num |
---|---|---|---|
1 | 张宇 | 1 | 370205621219253 |
2 | 王龙飞 | 2 | 370206501122483 |
3 | 聂海生 | 3 | 370203640507092 |
4 | 陈同贵 | 4 | 370206520713161 |
5 | 宋立嘉 | 5 | 370205551013054 |
5 | 宋立嘉 | 6 | 370206650615081 |
自然连接是一种特殊的等值连接,他要求两个关系表中进行连接的必须是相同的属性列(名字相同),无须添加连接条件,并且在结果中消除重复的属性列。
内连接:inner join
select * from account a inner join id_num i on a.account_id
= i.account_id
;
select * from account a join id_num i on a.account_id
= i.account_id
;
account_id | name | id | account_id | id_num |
---|---|---|---|---|
1 | 张宇 | 1 | 1 | 370205621219253 |
2 | 王龙飞 | 2 | 2 | 370206501122483 |
3 | 聂海生 | 3 | 3 | 370203640507092 |
4 | 陈同贵 | 4 | 4 | 370206520713161 |
5 | 宋立嘉 | 5 | 5 | 370205551013054 |
5 | 宋立嘉 | 6 | 5 | 370206650615081 |
自然连接和内连接有什么关系吗?
“自然连接”和“内连接”的区别,在于对“重合的相同的部分”处理方式不同
1."natrual join 自然连接"的处理方式:既然重复了,就丢掉一份,好比distinct
2.“inner join 内连接”的处理方式:虽然重复,但两份都保留。
左外连接:left [outer] join
select * from account a left outer join id_num i on a.account_id
= i.account_id
;
select * from account a left join id_num i on a.account_id
= i.account_id
;
account_id | name | id | account_id | id_num |
---|---|---|---|---|
1 | 张宇 | 1 | 1 | 370205621219253 |
2 | 王龙飞 | 2 | 2 | 370206501122483 |
3 | 聂海生 | 3 | 3 | 370203640507092 |
4 | 陈同贵 | 4 | 4 | 370206520713161 |
5 | 宋立嘉 | 5 | 5 | 370205551013054 |
5 | 宋立嘉 | 6 | 5 | 370206650615081 |
11 | 郑天民 | NULL | NULL | NULL |
12 | 王显平 | NULL | NULL | NULL |
右外连接:right [outer] join
select * from account a right outer join id_num i on a.account_id
= i.account_id
;
select * from account a right join id_num i on a.account_id
= i.account_id
;
account_id | name | id | account_id | id_num |
---|---|---|---|---|
1 | 张宇 | 1 | 1 | 370205621219253 |
2 | 王龙飞 | 2 | 2 | 370206501122483 |
3 | 聂海生 | 3 | 3 | 370203640507092 |
4 | 陈同贵 | 4 | 4 | 370206520713161 |
5 | 宋立嘉 | 5 | 5 | 370205551013054 |
5 | 宋立嘉 | 6 | 5 | 370206650615081 |
NULL | NULL | 21 | 21 | 370206340306481 |
NULL | NULL | 22 | 22 | 370727770614713 |
union/union all:
select account_id from account union all select account_id from id_num;
account_id |
---|
1 |
2 |
3 |
4 |
5 |
11 |
12 |
1 |
2 |
3 |
4 |
5 |
5 |
21 |
22 |
select account_id from account union select account_id from id_num;
account_id |
---|
1 |
2 |
3 |
4 |
5 |
11 |
12 |
21 |
22 |
全外连接:
select * from account a left join id_num i on a.account_id
= i.account_id
union
select * from account a right join id_num i on a.account_id
= i.account_id
;
account_id | name | id | account_id | id_num |
---|---|---|---|---|
1 | 张宇 | 1 | 1 | 370205621219253 |
2 | 王龙飞 | 2 | 2 | 370206501122483 |
3 | 聂海生 | 3 | 3 | 370203640507092 |
4 | 陈同贵 | 4 | 4 | 370206520713161 |
5 | 宋立嘉 | 5 | 5 | 370205551013054 |
5 | 宋立嘉 | 6 | 5 | 370206650615081 |
11 | 郑天民 | NULL | NULL | NULL |
12 | 王显平 | NULL | NULL | NULL |
NULL | NULL | 21 | 21 | 370206340306481 |
NULL | NULL | 22 | 22 | 370727770614713 |
select * from id_num i left join account a on a.account_id
= i.account_id
union
select * from id_num i right join account a on a.account_id
= i.account_id
;
id | account_id | id_num | account_id | name |
---|---|---|---|---|
1 | 1 | 370205621219253 | 1 | 张宇 |
2 | 2 | 370206501122483 | 2 | 王龙飞 |
3 | 3 | 370203640507092 | 3 | 聂海生 |
4 | 4 | 370206520713161 | 4 | 陈同贵 |
5 | 5 | 370205551013054 | 5 | 宋立嘉 |
6 | 5 | 370206650615081 | 5 | 宋立嘉 |
21 | 21 | 370206340306481 | NULL | NULL |
22 | 22 | 370727770614713 | NULL | NULL |
NULL | NULL | NULL | 11 | 郑天民 |
NULL | NULL | NULL | 12 | 王显平 |
全外连接(full outer join outer可以省略 )(mysql不支持)
mysql不支持全外连接,using和on的区别在于需要连接的两个表的属性名相同的时候使用using和on效果一样,而属性名不同的时候必须使用on。