小知识:
1.为表取别名
因为是对两张表进行查询了,那么每次写表名的话就有点麻烦,所以用一个简单的别名来代表表名
格式:表名 as 别名
2.为字段取别名
给字段名取别名的原因是为了有些字段名显示得更加清楚,比如:
select f_price as '价格' from fruits;
3.sql语句执行的顺序问题
sql执行顺序:(1) from (2) on (3) join (4) where (5) group by (6) avg, sum... (7) having (8) select (9) distinct (10) order by
也就是说,我们每次执行的sql语句都是从from开始的。
基于两张表
搭建查询环境:前面已经有了一张表了,现在再增加一张suppliers(供应商)表和前面那个fruits表创建练习,也就是说让fruits表中的s_id字段指向suppliers表的主键值,创建一个外键约束关系。
create table if not exists suppliers(
s_id int primary key not null comment '主键,供应商编号',
s_name varchar(50) not null comment '供应商名称',
s_city varchar(50) null comment '服务城市',
s_zip varchar(10) null comment '服务电话',
s_call varchar(20) not null comment '供应商电话') comment '供应商表';
其实这里并没有达到真正的外键约束关系,只是模拟,让fruits表中的s_id中的值能匹配到suppliers表中的主键值,通过手动添加这种数据,来达到这种关系,反正是死数据,也不再添加别的数据,就不用建立外键约束关系了,这里要搞清楚。
insert into suppliers(s_id, s_name, s_city, s_zip, s_call) values
(101, 'Supplies A', '天津', '400000', '18075'),
(102, 'Supplies B', '重庆', '400000', '44333'),
(103, 'Supplies C', '上海','400000', '90046'),
(104, 'Supplies D', '中山','400000', '11111'),
(105, 'Supplies E', '太原', '400000', '22222'),
(106, 'Supplies F', '北京', '400000', '45678'),
(107, 'Supplies G', '郑州', '400000', '33332');
1.普通双表连接查询
问题:查询水果的供应商编号、供应商名字、水果名称、水果价格
分析:看下要求,就知道要查询两张表,如果需要查询两张表,那么两张表的关系必定是外键关系,或者类似于外键关系(类似于也就是说两张表并没有真正加外键约束,但是其特点和外键是一样的,就像上面我们手动创建的两张表一样,虽然没有设置外键关联关系,但是其特性跟外键关系是一样的)。
select s.s_id, s.s_name, f.f_name, f.f_price from fruits as f, suplliers as s where f.s_id = s.s_id;
解释:这里使用了表别名,并且这里是连接两张表的关系是在于fruits中的s_id等于suppliers中的s_id,也说是fruits表中记录了供应商的编号,通过该编号就能在suppliers表中找到对应的供应商的详细信息,就这样,两张表就联系起来了。
注意:第一个执行的是from,所以上面为表取别名,在语句的任何地方都可以使用。
2.内连接查询
知道了上面两张表基本的连接查询后,内连接查询就很简单了,因为内连接跟上面的作用是一样的,唯一的区别就是语法的不一样
语法:表名 inner join 表名 on 连接条件;
问题:查询水果的供应商编号、供应商名字、水果名称、水果价格
select s.s_id, s.s_name, f.f_name, f.f_price from fruits as f inner join suppliers as s on f.s_id = s.s_id;
还需要知道一个特殊一点的东西,那就是自连接查询,什么是自连接查询?就是涉及到的两张表都是同一张表。
问题:查询供应商f_id = 'a1' 的水果供应商提供的其他水果种类
select f2.f_id, f2.f_name from fruits as f1 inner join fruits as f2 on f1.s_id = f2.s_id and f1.f_id = 'a1';
解释:把fruits表分开看成是两张完全一样的表,在f1表中找到f_id = 'a1' 的s_id,然后到f2这张表中去查找和该s_id相等的记录,也就查询出来了问题所需要的结果。还有另一种方法,不用内连接查询也可以做到,下面会讲解,这里先给出答案,到时可以回过头来看看这个问题。
select f_id, f_name from fruits where s_id = (select s_id from fruits where f_id = 'a1');
效果和内连接查询是一样的,其实原理都是一样的,还是借助了两张表,只是这个更容易让人理解,可以通过这个来去理解上面那个自连接查询。
3.外连接查询
内连接是将符合查询条件(符合连接条件)的行返回,也就是相关联的行就返回。
外连接除了返回相关联的行之外,将没有关联的行也会显示出来。
为什么需要将不没关联的行也显示出来呢?这就要根据不同的业务需求了,就比如,order和customers,顾客可以有订单也可以没订单,现在需要知道所有顾客的下单情况,而我们不能够只查询出有订单的用户,而把没订单的用户丢在一边不显示,这个就跟我们的业务需求不相符了,有人说,既然知道了有订单的顾客,通过单表查询出来不包含这些有订单顾客,不就能达到我们的要求吗,这样是可以,但是很麻烦,如何能够将其一起显示并且不那么麻烦呢?为了解决这个问题,就有了外连接查询这个东西了。
3.1 左外连接查询
语法:表名 left join 表名 on 条件;
返回包括左表中的所有记录和右表中连接字段相等的记录,通俗点讲,就是除了显示相关联的行,还会将左表中的所有记录行度显示出来。用例子来展示一下所说效果把。
由于上面我们所用到的fruits和suppliers中的记录都是设计好的,并没有哪个供应商没有提供水果,现在为了体现左外连接的效果,在suppliers中增加两条记录,fruits中并没有对应这两条记录得水果信息
insert into suppliers values
(108, 'Supplies T', '江西', '33333', '11111'),
(109, 'Supplier Y', '江西', '22222', '44444');
select s.s_id, s.s_name, f.f_id, f.f_name from suppliers as s left join fruits as f on s.s_id = f.s_id;
解释:suppliers表是在left join的左边,所以将其中所有记录度显示出来了,有关联项的,也有没有关联项的。这就是左外连接的意思,将左边的表所有记录都显示出来(前提是按照我们所需要的字段,也就是select 后面所选择的字段)。如果将suppliers表放left join的右边,那么就不会在显示108和109这两条记录了。来看看
select s.s_id, s.s_name, f.f_id, f.f_name from fruits as f left join suppliers as s on s.s_id = f.s_id;
3.2 右外连接查询
语法:表名 right join 表名 on 条件; 返回包括右表中的所有记录和右表中连接字段相等的记录,其实跟左外连接差不多,就是将右边的表内容给全部显示出来。
select s.s_id, s.s_name, f.f_id, f.f_name from friuts as f right join suppliers as s on s.s_id = f.s_id;
这条语句执行出来的效果跟上面左外连接一样,就是调换了一下位置,其实效果还是一样的。
注意:left join 和right join 这只是一种写法,其中还有另一种写法 left outer join 和 right outer join
一般写这种复杂查询的时候,写sql语句的顺序应该是先从from写起。
4. 复合条件连接查询
在连接查询(内连接、外连接)过程中,通过添加过滤条件,限制查询结果,使查询结果更加准确,通俗点讲,说是将连接查询时的条件更加细化。
问题一:在fruits和suppliers表中使用inner join语法查询suppliers表中s_id为107的供应商的供货信息?
select s.s_id, s.s_name, f.f_id, f.f_name from suppliers as s inner join fruits as f on s.s_id = f.s_id and s.s_id = 107;
问题二:在fruits表和suppliers表之间,使用inner join语法进行内连接查询,并对查询结果进行排序
select s.s_id, s.s_name, f.f_id, f.f_name from suppliers as s inner join fruits as f on s.s_id = f.s_id order by s.s_id; //对f.s_id进行升序排序,默认的是asc,所以不用写
对s.s_id进行排序其实也就是对f.s_id进行排序,效果是一样的,因为条件就是s.s_id=f.s_id。
子查询
子查询,将查询一张表得到的结果来充当另一个查询的条件,这样嵌套的查询就称为子查询
1. 带any、some关键字的子查询
搭建环境
create table if not exists tb11 (num1 int not null);
create table if not exists tb12 (num2 int not null);
insert into tb11 values (1), (5), (13), (27);
insert into tb12 values (6), (14), (11), (20);
any关键字接在一个比较操作符的后面,表示若与子查询返回的任何值比较为true,则返回true,通俗点讲,只要满足任意一个条件,就返回true。
select num1 from tb11 where num1 > any (select num2 from tb12);
这里就是将tb12表中查询的结果放在前一个查询语句中充当条件参数,只要num1大于其结果中的任意一个数据,那么就算匹配。
some关键字和any关键字的用法一样,作用也相同。
2. 带all关键字的子查询
使用all时表示需要同时满足所有条件
select num1 from tb11 where num1> all (select num2 from tb12);
num1需要大于所有查询到的结果才算匹配。
3. 带exists关键字的子查询
exists关键字后面的参数是任意一个子查询,如果子查询有返回记录行,则为true,外层查询语句将会进行查询,如果子查询没有返回任何记录行,则为false,外层查询语句将不会进行查询。
select * from tb11 where exists (select * from tb12 where num2 = 3); //查询tb12中有没有num2=3的记录,有的话则会将tb11的所有记录查询出来,没有的话,不做查询。
4. 带in关键字的子查询
这个in关键字的作用跟单表查询的in是一样的,不过这里in中的参数放的是一个子查询语句。
select s_id, f_id, f_name from fruits where s_id in (select s_id from suppliers whwre s_id = 107);
5. 带比较运算符的子查询
除了使用关键字all, any, some等之外,还可以使用普通的比较运算符来进行比较。比如我们上面讲解内连接查询的时候,就用过子查询语句,并且还是用的"="这个比较运算符,这里就不做多解释了,可以往上面看一下。
合并查询结果
利用union关键字,可以将查询出的结果合并到一张结果集中,也就是通过union关键字将多条select语句连接起来,注意:合并结果集,只是增加了表中的记录,并不是将表中的字段增加,仅仅是将记录行合并到一起。其显示的字段应该是相同的,不然不能合并。
union [all] 的使用
union:不使用关键字all,执行的时候会删除重复的记录,所有返回的行度是唯一的,
union all:不删除重复航也不对结果进行自动排序。
语法:select 字段名,... from 表名 union [all] select 字段名,... from 表名
问题:查询所有价格小于9的水果的信息,查询s_id等于101或103所有水果的信息,使用union连接查询结果
select s_id, f_name, f_price from fruits where f_price < 9 union all select s_id, f_name, f_price from fruits where s_id = 101 or s_id = 103;
解释:显示的字段都是s_id,f_name,f_price,只是将两个的记录行合并到一张表中。仅仅增加的是记录行,而显示的字段还是那三个,没有增加。
使用union,而不用union all的话,重复的记录将会被删除掉。
select s_id, f_name, f_price from fruits where f_price < 9 union select s_id, f_name, f_price from fruits where s_id = 101 or s_id = 103;
使用正则表达式查询
这个非常简单,就是使用regexp关键字来指定正则表达式,画一张表格,就能将下面所有的度覆盖掉。
1. 查询以特定字符或字符串开头的记录
select * from fruits where f_name regexp '^b'; //查询以b开头的记录
就讲解这一个,下面这些的形式跟这个一模一样,唯一的差别就在正则表达式不一样,一般使用这种模糊查询,使用mysql中的'_'和'%'就已经足够了。
2. 查询以特定字符或字符串结尾的记录
3. 用符号"."来替代字符串中的任意一个字符
4. 使用"*"和"+"来匹配多个字符
5. 匹配指定字符串
6. 匹配指定字符中的任意一个
7. 匹配指定字符以外的字符
8. 使用{n,}或者{n,m}来指定字符串连续出现的次数
标签:多表,name,suppliers,mysql,查询,fruits,id,select From: https://www.cnblogs.com/k0065/p/17610358.html