mysql学习三:查询表

 

一条完整的sql语句:
select xxx
from xxx
where xxx
group by xxx
having xxx
order by xxx
limit xxx

 

以上语句的执行顺序:

1. from 将硬盘上的表文件加载到内存

2. where 将符合条件的数据进行过滤。生成一张新的临时表

3. group by 根据列中的数据种类,将当前临时表分成若干个新的临时表

4. having 过滤掉group by生成的不符合条件的临时表

5. select 对当前临时表进行整列读取

6. order by 对select生成的临时表,进行重新排序,生成新的临时表

7. limit 对最终生成的临时表的数据行,进行截取

 跨表查询:

    • 1.内连接,省略了inner,完整的应该是inner join。查询中的比较次数:表1记录 * 表2记录 * .... 表N
      • 等值连接
        # 查询员工所对应的部门名称:如果某员工没有部门或者某部门没有员工,则这两条记录都不会显示
        select
        e.ename,d.dname from emp e join dept d on e.deptno=e.deptno;
      • 非等值连接
        # 查出员薪水对应的薪水等级:
        select e.ename,e.sal,s.grade from emp e 
        join salgrade s on e.sal between s.losal and s.hisal;
      • 自连接,看一张表当作两张表看
        # 查出员工对应的经理名字
        select
        a.ename,b.ename from emp a join emp b on a.mgr=b.empo;
    • 2.
      外连接:A表和B表能够完全匹配的记录查询出来之外(内连接),将其中一张表的记录无条件的完全查询出来,对应表没有匹配的记录时,会自动模拟出null值与之匹配。外连接的查询结果条数 >= 内连接的查询结果条数。省略了outer,完整的为left | right outer join

 

      •   左外连接/左连接:包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行。      示例:显示所有员工,及其部门;如果员工存在但对应的部门不存在,也要显示,部门显示为null。假设左表为员工表,右表为部门表,此时,需要用左外连接(左边的表全显示,右边的表符合条件的显示,不符合条件的显示null)。
        # 左外连接:左边的行全部无条件显示
        # 如果有一个员工,没有部门,则左外连接的查询结果会包含此员工,部门null
        select e.ename,d.name
        from emp e
        left join dept d on e.deptno=d.deptno;
      • 右外连接/右连接:包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行。     示例:显示所有部门,及其对应的员工;如果某部门存在但不存在员工,也要显示此部门,员工姓名显示为null。假设左表为员工表,右表为部门表,此时,需要用右外连接(右边的表全显示,左边的表符合条件的显示,不符合条件的显示为null)
        # 右外连接:右边的行全部无条件显示
        # 如果有一个部门,没有员工,则右外连接的查询结果会包含此部门,员工姓名为null
        select e.ename,d.name
        from emp e
        right join dept d on e.deptno=d.deptno;
  • 3.全连接:包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。

 

 

示例:查出员工的部门名称,员工的领导名称和薪水等级

select d.dname,e.ename,b.ename as leadername 
from emp e 
join dept d on e.deptno=d.deptno 
join emp b on e.mgr=b.empno 
join salgrade s on e.sal between s.losal and s.hisal;

 

子查询:select语句嵌套select语句,称为子查询。

注意:select子句,可以出现在select、from、where关键字后面。

select .........(select 子查询)........
from .........(select 子查询)........
where .........(select 子查询)........

 

示例:找出薪水比公司平均薪水高的员工,要求显示员工名和薪水

select ename,sal 
from emp 
where sal > select avg(sal) as avgsal from emp;

 

查出部门的平均薪水,并显示平均薪水的薪水等级

select t.avgsal,s.grade
from (select e.deptno,avg(e.sal) avgsal from emp group by e.deptno) t
join salgrade s on t.avgsal between s.losal and s.hisal;

 合并查询:union,合并相加结果集。

示例:查询出工作岗位为manager和salesman的员工

# 方法一:
select ename,job from emp where job='manager' or job='salesman'
# 方法二:
select ename,job from emp where job in ('manager','salesman')
# 方法三:
select ename,job from emp where job='manager'
union
select ename,job from emp where job='salesman'

 

使用union的两个查询结果集的字段要相同。

 

 

创建学生表:

CREATE TABLE `db_student`  (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `stuName` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` smallint(4) NOT NULL,
  `gradeName` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

 

INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (1, '张三', '', 21, '一年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (2, '张x', '', 23, '一年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (3, '张y', '', 25, '三年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (4, '张三', '', 23, '一年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (5, '张三', '', 18, '一年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (6, '刘一', '', 23, '一年级');
INSERT INTO `db_student`.`student`(`id`, `stuName`, `sex`, `age`, `gradeName`) VALUES (10, '王九', '', 22, '一年级');

 

 一、单表查询:

1.

select distinct gradeName from db_student;
select * from db_student order by age asc;  # 默认asc升序;降序desc

 

2.分组查询:

group by 字段名 [having 条件表达式] [with rollup]

  • 单独使用(无意义)group by 字段名;
  • 与group_concat()函数一起使用;
    select gradeName, group_concat(stuName) from student group by gradeName;

    根据分组结果(一年组、三年级),将每组中的stuName以逗号分隔组成一个字段返回group_concat(stuName)

  • 与聚合函数一起使用;
    # 查看每个年级的学生总数
    select gradeName,count(stuName) from student group by gradeName;

    根据分组结果,统计每组中的学生总数count(stuName)

  • 与having一起使用;

    # 查看学生总数大于3的年级:首先根据年级分组,然后having过滤学生总数大于3
    select gradeName,count(stuName) from student group by gradeName having count(stuName) > 3;

  • 与with rollup一起使用(最后加入一个总和行)
    # with rollup:在最后一行,增加一个总和行
    select gradeName,count(stuName) from student group by gradeName with rollup;

    # with rollup:如果聚合函数的结果不是数值,是文字,则将所有文字连接起来,以逗号分隔
    select gradeName,group_concat(stuName) from student group by gradeName with rollup;

limit:limit 起始位置,记录数

 

3、使用聚合函数:count、sum、avg、max、min  通常与group by联合使用

 

create table grade (
id int,
stuName varchar(60),
course varchar(60),
score int
);
insert into grade (id, stuName, course, score) values (1, '张三','语文', '91');
insert into grade (id, stuName, course, score) values (2, '张三','数学', '90');
insert into grade (id, stuName, course, score) values (3, '张三','英语', '87');
insert into grade (id, stuName, course, score) values (4, '李四','语文', '95');
insert into grade (id, stuName, course, score) values (5, '李四','数学', '80');
insert into grade (id, stuName, course, score) values (6, '李四','英语', '77');
insert into grade (id, stuName, course, score) values (7, '王五','语文', '81');
insert into grade (id, stuName, course, score) values (8, '王五','数学', '60');
insert into grade (id, stuName, course, score) values (9, '王五','英语', '50');

 count:统计条数

select count(*) from grade;
select count(*) as total from grade;
# 9
# 统计每个学生考试的总科目
select stuName,count(*) as total from grade group by stuName;

sum:求和

#求出张三的总分
select stuName, sum(score) from grade where stuName='张三';
#根据学生分组,查出每个学生的总分
select stuName, sum(score) from grade group by stuName;

 

 

avg:求平均

#求出张三的平均成绩
select stuName, avg(score) from grade where stuName='张三';
#89.3
# 求出所有学生的平均成绩
select stuName, avg(score) from grade group by stuName;

 

 

max:求最大值

#求出张三的最高成绩
select stuName, max(score) from grade where stuName='张三';
#求出每个学生的最高分
select stuName,  max(score) from grade group by stuName;

min:求最小值

select stuName,  min(score) from grade where stuName='张三';
#求出每个学生的最低分
select stuName,  min(score) from grade group by stuName;

 

 

 二、连接查询

create table `book` (
`id` int(11) not null auto_increment,
`bookName` varchar(20) default null,
`price` decimal(6,2) default null,
`author` varchar(20) default null,
`bookTypeId` int(11) default null,
primary key (`id`)
) engine=innodb auto_increment=5 default charset=utf8;
create table `bookType` (
`id` int(11) not null auto_increment,
`bookTypeName` varchar(20) default null,
primary key (`id`)
) engine=innodb auto_increment=5 default charset=utf8;

 

 连接查询:是将两个或两个以上的表按照某个条件连接起来,从中选取需要的数据。

select * from book,bookType;

 结果为:book的记录数 * bookType的记录数

1.内连接查询:是一种最常用的连接查询,查询两张或多张表的信息

select * from book,bookType where book.bookTypeId=bookType.id;

select b.bookName,b.author,bt.bookTypeName from book b,bookType bt where b.bookTypeId=bt.id;

2.外连接查询:联合多张表,查出一张表的所有信息,其它表的信息要看条件

 select 字段列表 from 表1 left|right join 表2 on 表1.字段x=表2.字段x; 

 

1)左连接:查出表1的所有记录,而表2中,只能查出匹配的记录;

select * from book b left join bookType bt on b.bookTypeId=bt.id;

 

2)右连接:查出表2的所有记录,而表1中,只能查出匹配的记录;

select * from book b right join bookType bt on b.bookTypeId=bt.id;

 

三、子查询:子查询的结果,作为结果集或某一具体的值,用于条件判断

create table pricelevel (
id int,
priceLevel int,
price float,
description varchar(300)
)
insert into pricelevel (id, priceLevel, price, description) values ('1', '1', '90.00', ''),('2', '2','60.00','适中'),('3','3','20.00','便宜');

1.带in关键字的子查询:一个查询语句的条件可能落在另一个select语的查询结果中

# 查询book表,要求book表中的bookType要在bookType表中
select id from bookType;
select * from book where bookTypeId in (select id from bookType);
select * from book where bookTypeId not in (select id from bookType);

子查询select id from bookType的查询结果:注意子查询中应该说明要查询的字段,否则无法得到集合

第二条语句的条件:即book表的bookTypeId的值 ,要在上面的子查询结果集中;相当于 bookTypeId in (1, 2)

第三条语句:bookTypeId的值,不在子查询的结果集中;相当于 bookTypeId not in (1, 2)

 

2.带比较运算符的子查询:子查询可以使用比较运算符

#查询比较贵的书:pricelevel表中priceLevel=1的是比较贵的,把它作为比较条件
select price from pricelevel where priceLevel=1;
select * from book where price >= (select price from pricelevel where priceLevel=1);

子查询语句的查询结果:注意子查询的结果应该要说明要查询的字段,否则无法比较

第二条语句:与子查询的结果,比较

3.带exists关键字的子查询:假如子查询,查询到记录,则进行外层查询;否则,不执行外层的查询

#查book表,假如booktype表中有数据,则查询book表
select * from booktype;
select * from book where exists (select * from booktype);
# 假如booktype表中没有数据,则查询book表
select * from booktype;
select * from book where not exists (select * from booktype);

 

第一条语句:查询是有数据的

第二语句:exists (子查询,第一条语句是有数据的),返回True;则查询所有的book记录

第三条语句:not exists (子查询),如果子查询的结果没有数据,则为True,查询所有的book记录;否则不查询book表

4.带any关键字的子查询:表示只要满足子查询中的任何一个条件

#查book表;只要book表的价格price大于任何一个pricelevel中的价格,即符合条件
select price from pricelevel;
select * from book where price >= any (select price from pricelevel);

 

第一条语句:子查询的结果集

第二条语句:price 大于等于,必须是一个具体的数值;而上面的子查询结果是一个集合,使用any,即可满足和大于等于的比较;同时只要any子查询的结果中的任何一个条件满足,即满足

5.带all关键字的子查询:all关键字,表示要满足所有条件

select * from book where price >= all (select price from pricelevel);

 

 四、合并查询

1.union:使用union关键字,数据库系统会将所有的查询结果合并到一起,然后去除掉相同的记录

2. union all:不会去重;

select id from book;
select id from booktype;
select id from book union select id from booktype;
select id from book union all select id from booktype;

第一条语句的查询结果:

第二条语句查询的结果:

第三条语句的结果:

第四条语句:

 

posted on 2018-09-15 19:57  myworldworld  阅读(574)  评论(0)    收藏  举报

导航