0


MySQL学习(八)SQL进阶版

1.聚合查询

1.1聚合函数

常见的聚合函数如下:

用法很简单,当正常函数使用即可,如查询数学的平均值:

  1. select avg(math) from exam_result;

1.2聚合字段

聚合字段是指按哪个字段进行聚合,聚合类似分组的意思,通常看到计算同类产品,相同产品等统计工作时我们就需要按照某字段属性进行聚合查询

关键字:group by(某字段)

如求各公司总数,就要按公司字段进行聚合:

  1. select company, count(*) from emp2 group by company;

1.3多聚合

如果要按照多个字段逐级去聚合,就叫多聚合

多聚合的各个字段用逗号分隔即可,如:

  1. select company, depart, role, count(*)
  2. from emp2
  3. group by company, depart, role;

返回结果:依次按公司、部门、角色进行聚合

1.4having关键字

【注意】聚合之后,也是可以继续使用其它诸如排序、分页等操作

如继续使用排序:

  1. select company, depart, count(*)
  2. from emp2
  3. group by company, depart
  4. order by count(*);

但是!!!如果聚合后要继续进行过滤条件的话,不能继续使用where了,要使用having

  1. select company, depart, role, count(*)
  2. from emp2
  3. group by company, depart, role
  4. having count(*) = 1;

ps:having & where

where筛选的是数据库中本来就有的字段,是先where筛选再select,而having是先select再having筛选,是在已经筛选过的新库表里再having

2.联表查询

所谓联表查询,就是查询结果需要在多张表上进行联合查询;

多表查询的结果是对多张表取笛卡尔积

2.1 普通联表查询

【ps】普通联表查询默认为内连接

(1)直接from后跟联表名称,用逗号隔开

以联合查询users表和articles表为例,原表数据如下:

联表查询:

  1. -- from 后边直接跟 2 张表(2 张以上也可以)
  2. -- 视为同时从 2 张表中查询数据
  3. select * from users, articles; -- 一共 6 条数据 = 2 * 3

结果:

(2)使用join关键字

  1. select * from users join articles;

结果一样:

2.2 +过滤条件

(1)直接逗号连接的,可直接加where语句

  1. -- 添加 联表 条件后,得到的结果才是有意义的
  2. select *
  3. from users, articles
  4. where users.uid = articles.author_id;

不止一个过滤条件的,接着用and

  1. select *
  2. from users, articles
  3. where uid = author_id and users.name = '小红';

(2)用join连接的,可以用关键词on进行条件过滤(用where也不会报错,但是(1)中没有join而用on却会报错)

  1. select *
  2. from users join articles
  3. on uid = author_id;

(3)

  1. select *
  2. from users, articles
  3. where uid = author_id and users.name = '小红';
  4. select *
  5. from users
  6. join articles
  7. on uid = author_id
  8. where users.name = '小红';
  9. select *
  10. from users
  11. join articles
  12. on uid = author_id and users.name = '小红';

以上三种写法是相同的意思,均正确

2.3 内连接

以上连接均为内连接,实则是省略了inner这个单词

  1. select *
  2. from users
  3. inner join articles -- inner 可以省略
  4. on uid = author_id;

2.4 左外连 and 右外连

左外连和右外连共同构成了外连接

  • 左外连:left outer join,左侧的表完全显示
  • 右外连:right outer join,右侧的表完全显示

其中,outer这个单词可以省略不写

为了便于理解,我们稍微修改一下原表数据

可以看到,当我们要找uid==author_id时,左表中的序号2在右表中无对应行,而右表中的序号3在左表中无对应行

🤨🤨🤨对于内连接:只会显示所有匹配的上的

  1. select *
  2. from users
  3. inner join articles -- inner 可以省略
  4. on uid = author_id;

🤨🤨🤨来看左外连:

  1. -- 左外联
  2. select *
  3. from users
  4. left outer join articles
  5. on uid = author_id;

🤨🤨🤨再来看右外连:

  1. -- 右外联
  2. select *
  3. from users
  4. right outer join articles
  5. on uid = author_id;

2.5 自连接

自连接就是同一张表连接自己进行查询

典型例子:查询计算机原理成绩比java成绩高的同学(因为是同一个同学的不同字段比较查询,所以需要自连接查询,自连接查询至少要给其中一张自己起个别名,便于区分)

先看原表结构:

成绩score表

学生信息student2表

课程信息course表

  • 先自连接查询:
  1. select s1.student_id
  2. from score s1
  3. join score s2
  4. -- 只保留自连接结果中相同学号的行
  5. on s1.student_id = s2.student_id
  6. -- 计算机原理的课程编码为3
  7. where s1.course_id = 3
  8. -- Java的课程编码为1
  9. and s2.course_id = 1
  10. and s1.score > s2.score;

查询结果:

这样的查询结果没啥用,看不到是谁

  • 所有我们优化一下,三张表都连接一下,返回详细信息
  1. -- 联合查询
  2. select student2.id,student2.name,s1.score 计算机原理,s2.score Java
  3. from score s1
  4. join score s2
  5. -- 同一名学生的
  6. on s1.student_id = s2.student_id
  7. -- course表中找课程id
  8. and s1.course_id in (select id from course where course.name = '计算机原理')
  9. and s2.course_id in (select course.id from course where course.name = 'Java')
  10. and s1.score > s2.score
  11. -- 连接student2表,获取学生信息
  12. join student2
  13. on s1.student_id = student2.id;

3.子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

3.1 单行子查询

直接小括号嵌套即可:

  1. select *
  2. from student
  3. where classes_id = (select classes_id from student where name='不想毕业');

3.2 多行——in / not in

如上面刚写过的查找课程编号操作:

in:存在

not in :不存在

3.3 多行——exists / not exists

  1. -- 使用 EXISTS
  2. select *
  3. from score sco
  4. where exists (
  5. select sco.id from course cou where (name='语文' or name='英文') and cou.id = sco.course_id
  6. ) order by id;

3.4 in & exists 区别

可以理解为:

in:先执行内部查询,就是先去找满足in内部的条件查询,然后在找到的符合条件里再执行外部查询继续筛选

exists:先通过外部的 sql 得到结果,将每行的结果,代入到内部的exists里的 sql中,,如果能得到结果(行数 > 0),说明满足了 exists 的条件,将满足的返回结果

4.合并查询

(1)union 合并重复行

(2)union all 不合并重复行

【】注意,用union合并的查询,最后有一个分号即可

如:

组合 Products 表中的产品名称和 Customers 表中的顾客名称_牛客题霸_牛客网 (nowcoder.com)

  1. select prod_name from Products
  2. union
  3. select cust_name prod_name from Customers
  4. order by prod_name;

5.真题题解

1.返回 2020 年 1 月的所有订单的订单号和订单日期_牛客题霸_牛客网 (nowcoder.com)

  1. select order_num,order_date
  2. from Orders
  3. where year(order_date) = 2020
  4. and month(order_date) = 1
  5. order by order_date;

2.顾客登录名_牛客题霸_牛客网 (nowcoder.com)

  1. select cust_id,cust_name,
  2. upper(concat(substr(cust_contact,1,2),substr(cust_city,1,3))) user_login
  3. from Customers;

由这两道题,除了上文中写到的聚合函数,我们再来扩展一些常用到的函数:

(1)字符串函数

  • upper()——转大写
  • lower()——转大写
  • substr(string,start,length)——截取从start开始长度为length个范围内的字符(start从1开始)
  • concat(str1,str2)——拼接两个字符串

(2)日期和时间函数

  • month()——返回月
  • year()——返回年

3.计算总和_牛客题霸_牛客网 (nowcoder.com)

  1. select order_num,sum(item_price * quantity) total_price
  2. from OrderItems
  3. group by order_num
  4. having total_price >= 1000;

4.确定最佳顾客的另一种方式(二)_牛客题霸_牛客网 (nowcoder.com)

  1. select cust_name,total_price
  2. from Customers c
  3. join Orders o
  4. on o.cust_id = c.cust_id
  5. join(
  6. select oi.order_num,sum(item_price * quantity) total_price
  7. from OrderItems oi
  8. group by oi.order_num
  9. having total_price >= 1000
  10. ) j
  11. on j.order_num = o.order_num
  12. order by total_price;

5.返回产品名称和每一项产品的总订单数_牛客题霸_牛客网 (nowcoder.com)

  1. select prod_name,ifnull(orders,0) orders
  2. from Products p
  3. left outer join
  4. (select prod_id,count(order_num) orders
  5. from OrderItems
  6. group by prod_id) j
  7. on p.prod_id = j.prod_id
  8. order by prod_name;

6.返回每个顾客不同订单的总金额_牛客题霸_牛客网 (nowcoder.com)

  1. select o.cust_id,total_ordered
  2. from Orders o
  3. join
  4. (select order_num,sum(item_price * quantity) total_ordered
  5. from OrderItems
  6. group by order_num) t
  7. on o.order_num = t.order_num
  8. order by total_ordered desc;

标签: 数据库

本文转载自: https://blog.csdn.net/m0_58652786/article/details/124123443
版权归原作者 笨笨在努力 所有, 如有侵权,请联系我们删除。

“MySQL学习(八)SQL进阶版”的评论:

还没有评论