创建两个表,并添加如下数据(此表对以下讨论均适用)
#user_info表
create table user_info(
id int(2) primary key,
user_name varchar(12) unique,
password varchar(15) not null,
real_name varchar(8) not null,
age int(3)
);
#address表
create table address(
id int(2) primary key,
user_id int(2) not null, #user_id是uesr_info表中的id,是理论上的外键,将两个表联系起来,可以插入垃圾数据
real_name varchar(8),
mobile char(11),
address varchar(150)
);
insert into user_info values(1,'浅唱灬幸福','8912@321','王晓明',12);
insert into address values(1,1,'王小明','15516472282','山西太原');
insert into address values(2,1,'王鑫','18404905139','山西大同');
insert into address values(3,1,'任建','15333021730','山西晋城');
insert into user_info values(2,'ぅ浮生若梦〤','56701wz','王楠',36);
insert into address values(4,2,'王楠','15010303314','北京海淀');
insert into address values(5,2,'赵婕','18435224278','山西长治');
insert into user_info values(3,'街角の风铃','27w4921','李晓飞',9);
insert into address values(6,6,'刘倩','13159775555','吉林长春'); #垃圾数据,但可以添加成功
在讨论多表查询之前,首先讨论子查询,以此引出多表查询。
什么是子查询:
查询中的查询即为子查询,一般使用括号将子查询sql括起来,如下SQL语句: select * from (select * from user_info) users
什么时候用子查询:
当在查询过程中需要知道一个已知量的不确定数据时使用子查询
例如:查询出来姓名为王晓明的所有地址
思路:需要先根据王晓明(已知量)查出user_info表中的id,再根据id=user_id,在地址表中查出所有的地址信息(不确定数据)
1,一般情况,我们会用两条SQL语句查询,如下
select id from user_info where real_name='王晓明' #首先得到的是王晓明的id
select * from address where user_id=1 #再根据id在地址表中查询
2,事实上,我们学习了子查询后可以用子查询的方法,如下SQL语句
select * from address where user_id=(select id from user_info where real_name='王晓明'); #使用子查询先通过姓名获取id,然后再通过用户id查询地址表
注意“=”:如果子查询只返回一个结果,则可以使用=,也可以使用in;但是如果确定子查询永远只返回一个结果,则不建议使用in,例如上面SQL语句可变为如下SQL语句
select * from address where user_id in(select id from user_info where real_name=‘王晓明’);
3,上述子查询前一个SQL语句只返回了一个结果,如果子查询返回多个结果,则使用in
查询所有姓王的地址信息,先使用一般方法
select id from user_info where real_name like '王%' #执行此语句会返回多个值。
select * from address where user_id in(1,2) #上述语句返回了多个值,所以用in
select * from address where user_id in(select id from user_info where real_name like '王%')
上述输出结果知识address中的信息,并不能直观的看见user_info中的信息,使用多表查询可以显示出两个表中的数据,接下来讨论多表查询。
多个表关联查询需要依据多表之间列关系将其连接起来,这种连接方式分为三种:内连接(inner join)、外连接(outer join)及交叉连接(cross join)
如果依据多表之间列关系进行外连接,查询结果集不仅仅包括满足on连接条件的数据行,还包括不满足on连接条件的数据行。
左外连接(left [outer] join):返回的结果集中不仅包含表之间满足on连接条件的全部数据行,还包含左表(“left [outer] join”关键字左边的表)不满足on连接条件的数据行;
执行如下SQL语句
select ui.*,addr.*
from user_info as ui
left join address as addr
on addr.user_id=ui.id
上述输出结果中字段名为id且id为3的数据存在于左边表中,但是在右边表中没有对应的地址,并不满足on中的条件,依旧显示。
右外连接(right [outer] join):返回的结果集中不仅包含表之间满足on连接条件的全部数据行,还包含右表(即“right [outer] join”关键字右边的表)不满足on连接条件的数据行;
select ui.*,addr.*
from user_info as ui
right join address as addr
on addr.user_id=ui.id
上述输出结果中,字段名为id(1)且id(1)为3的数据存在于右边表中,在左边表中没有对应的用户名,也会输出。
总结左右连接:以left或right为参照,如果是left,则显示该关键字左边表中所有数据,如果从表没有对应的数据,则显示null;同样,如果是right,则显示该关键字右边表中所有数据,如果从表没有对应的数据,则显示null
全外连接(full [outer] join):返回的结果集中不仅包含表之间满足on连接条件的全部数据行,还包含左表(“full [outer] join”关键字左边的表)和右表(“full [outer join”关键字右边的表)中不满足on连接条件的数据行;
select ui.*,addr.*
from user_info as ui
full join address as addr
on addr.user_id=ui.id #语句正确
MySQL数据库不支持全连接,以下结果为orcal数据库中输出的
如果依据多个表之间列关系进行内连接,查询结果集仅包括满足连接条件的数据行。内连接分为等值连接、不等值连接以及自然连接,其中等值连接最为常见。
下边介绍等值连接:查询出的结果为两个表共有的,是交集。
select ui.*,addr.*
from user_info as ui
inner join address as addr
on addr.user_id=ui.id
左表(“cross join”关键字左边的表)中的每一行与右表(“cross join”关键字右边的表)中的所有行组合,交叉联接的结果是一个笛卡尔积。
select ui.*,addr.*
from user_info ui
cross join address addr order by real_name; #为了直观传达信息,将连接后的数据根据real_name排序。输出结果更加直观的得到是两个表中数据(认为一行为一条数据)的笛卡尔积,共18条数据。