day 04 DQL数据查询语言---单表查询

由于sql语句不区分大小写,为了书写方便,本文所有命令统一使用小写

 往期内容

目录

一、数据处理函数

二、多行数据处理函数

三、总结

四、习题


一、数据处理函数

concat(字段名1,字段名2.....      #字符串的拼接 

#将教师的工号与姓名进行拼接

mysql> select concat(teno,tename) as noname from t_teacher;
+----------+
| noname   |
+----------+
| 9801点赞 |
| 9802关注 |
| 9803收藏 |
| 9804订阅 |
+----------+
4 rows in set (0.00 sec)

length(字段名       #取长度

#查询教师英文名字的长度

mysql> select tename,length(Englishname) as namelength from t_teacher;
+--------+------------+
| tename | namelength |
+--------+------------+
| 点赞   |          7 |
| 关注   |          6 |
| 收藏   |          6 |
| 订阅   |          5 |
+--------+------------+
4 rows in set (0.00 sec)

综合题目

将教师的英文名字改成首字母大写,其他字母小写,并查询出来

mysql> select
    -> tename,concat(substr(Englishname,1,1),lower(substr(Englishname,2,length(Englishname)-1)))
    -> as
    -> Englishname
    -> from
    -> t_teacher;
+--------+-------------+
| tename | Englishname |
+--------+-------------+
| 点赞   | Blake       |
| 关注   | Turner      |
| 收藏   | Miller      |
| 订阅   | Clark       |
+--------+-------------+
4 rows in set (0.01 sec)

trim (' 值'          #去除括号内字符串中的空格

mysql> select * from t_teacher where tename=trim('            点赞');
+------+--------+-------------+----------+---------+------------+
| teno | tename | Englishname | tesalary | teclass | hiredate   |
+------+--------+-------------+----------+---------+------------+
| 9801 | 点赞   | BLAKE       |  8500.00 | 1班     | 2005-03-17 |
+------+--------+-------------+----------+---------+------------+
1 row in set (0.00 sec)

case..when..then..when..then..else..end    语句

当满足......条件时做......,当满足......条件时做......当满足......条件时做......

#1班的教师工资上调30%,2班的老师工资上调20%,其他教师下调10%

mysql> select
    -> tename,teclass,tesalary as oldsal,
    -> (case teclass when '1班' then tesalary*1.3 when '2班' then tesalary*1.2 else tesalary*0.9 end) as newsalary
    -> from
    -> t_teacher;
+--------+---------+----------+-----------+
| tename | teclass | oldsal   | newsalary |
+--------+---------+----------+-----------+
| 点赞   | 1班     |  8500.00 |  11050.00 |
| 关注   | 3班     |  9300.00 |   8370.00 |
| 收藏   | 2班     | 13200.00 |  15840.00 |
| 订阅   | 4班     |  8800.00 |   7920.00 |
+--------+---------+----------+-----------+
4 rows in set (0.00 sec)

round(字段名,参数     四舍五入

round(字段名,0)    保留到个位数

round(字段名,1)     保留一位小数

round(字段名,2)     保留两位小数

round(字段名,-1)    保留到个位数

round(字段名,-2)    保留到十位数

#将2班的数学成绩四舍五入保留到十位数

mysql> select
    -> stname,stmath as oldmath,
    -> round(stmath,-1) as newmath
    -> from
    -> t_student
    -> where
    -> stclass='2班';
+--------+---------+---------+
| stname | oldmath | newmath |
+--------+---------+---------+
| 李四   |      43 |      40 |
| 东西   |      34 |      30 |
| 左右   |      88 |      90 |
| 周一   |      68 |      70 |
| 周四   |      94 |      90 |
| 周日   |      69 |      70 |
| 赵六   |      76 |      80 |
| 周五   |      99 |     100 |
| 冷烬   |     100 |     100 |
+--------+---------+---------+
9 rows in set (0.00 sec)

rand()         #默认生成0-1的随机小数

与round组合可以生成随机整数,当数据量够大且连续时,可以用于where

#演示一下随机生成10以内的整数,不报错,但也无意义

mysql> select round(rand()*10,0) from t_teacher;
+--------------------+
| round(rand()*10,0) |
+--------------------+
|                  5 |
|                  7 |
|                  9 |
|                  2 |
+--------------------+
4 rows in set (0.00 sec)

ifnull(字段名, 被当做哪个值  #若为null改成xxx,null参与运算时,结果都为null

#null表示缺考,找出并改为0

mysql>  select
    -> stname,stmath,ifnull(stmath,0) as newmath
    -> from
    -> t_student
    -> where
    -> stmath is null;
+--------+--------+---------+
| stname | stmath | newmath |
+--------+--------+---------+
| 南北   |   NULL |       0 |
+--------+--------+---------+
1 row in set (0.00 sec)

二、多行数据处理函数

多行数据处理函数也叫分组函数,即使用时必须先进行分组,不然会默认整张表为一个组

特点:输入为多行,输出只有一行,自动忽略null

常见的有:count计数;sum 求和;avg 平均值;max 最大值;min 最小值

注!!!!!!!

count(字段名)与count(*)的区别 

前者只计算该字段名的数据不为空的个数

后者计算该行至少有一个不为空的行数

用法:都为 函数名(字段名) 

不进行分组,只能计算全部的,不能计算各班的!!!

分组函数不能运用在where语句上!!!!!

mysql> select avg(stmath) from t_student;
+-------------+
| avg(stmath) |
+-------------+
|     76.0400 |
+-------------+
1 row in set (0.04 sec)

 分组函数可以一起使用 

mysql> select
    -> sum(stmath),min(stmath),max(stmath),avg(stmath),count(stmath)
    -> from
    -> t_student;
+-------------+-------------+-------------+-------------+---------------+
| sum(stmath) | min(stmath) | max(stmath) | avg(stmath) | count(stmath) |
+-------------+-------------+-------------+-------------+---------------+
|        1901 |          34 |         100 |     76.0400 |            25 |
+-------------+-------------+-------------+-------------+---------------+
1 row in set (0.04 sec)

 distinct   去除重复值

select distinct 字段名1,.....from 表名。。。 

distinct只能放在所有字段的最前面,distinct后面如果有多个字段,表示联合去重

mysql> select distinct stclass from t_student;
+---------+
| stclass |
+---------+
| 1班     |
| 3班     |
| 2班     |
+---------+
3 rows in set (0.00 sec)
mysql> select distinct stclass,stsex from t_student;
+---------+-------+
| stclass | stsex |
+---------+-------+
| 1班     | 男    |
| 3班     | 女    |
| 1班     | 女    |
| 2班     | 男    |
| 3班     | 男    |
+---------+-------+
5 rows in set (0.00 sec)

 与count()结合,统计有多少个班

mysql> select count(distinct stclass) from t_student;
+-------------------------+
| count(distinct stclass) |
+-------------------------+
|                       3 |
+-------------------------+
1 row in set (0.00 sec)

 分组语法

select  字段名  from   表名  where  条件  group by  字段名;

#计算各个班的平均分

mysql> select
    -> stclass,avg(stmath)
    -> from
    -> t_student
    -> group by
    -> stclass;
+---------+-------------+
| stclass | avg(stmath) |
+---------+-------------+
| 1班     |     77.0000 |
| 3班     |     76.7143 |
| 2班     |     74.5556 |
+---------+-------------+
3 rows in set (0.04 sec)

注!!!!!!

group by  语句中,select 后面只能跟分组的字段和分组函数,其他都不能跟,虽然MySQL不会报错,但oracle会报错,而且这样写毫无意义。


联合分组

select  字段名  from   表名  where  条件  group by  字段名1,字段名2......;

将两个及两个以上的字段联合起来分组,即将多个字段看成一个字段!

#查询不同班级中,不同性别的平均数学成绩和数学最高分

mysql> select
    -> stclass,stsex,avg(stmath) as avgmath,max(stmath) as maxmath
    -> from
    -> t_student
    -> group by
    -> stclass,stsex;
+---------+-------+---------+---------+
| stclass | stsex | avgmath | maxmath |
+---------+-------+---------+---------+
| 1班     | 男    | 72.0000 |      91 |
| 3班     | 女    | 74.8000 |      88 |
| 1班     | 女    | 79.5000 |      93 |
| 2班     | 男    | 74.5556 |     100 |
| 3班     | 男    | 81.5000 |      89 |
+---------+-------+---------+---------+
5 rows in set (0.00 sec)

上述结果正确,2班没女生是在造数据时考虑不全导致的!!!!


having 语句效果和where一样

区别:

  • 执行顺序不一样where语句比group先执行,所以不能只有分组函数,而having可以
  • 筛选对象不一样,where是对分组前的数据进行筛选,而having是对筛选后的数据进行筛选
  • 执行效率不一样where效率比having高,因为having使用之前必须先执行分组操作,即使没有写group语句,也会自动将整张表分成一个组再执行having语句,所以能用where就不要用having!!!!

 例子:找出各个班的最高分,显示高于90分的班级

方法一:先分组再用having语句筛选

需要先遍历全表进行分组,再遍历全表找出最高分的

注!!!!

having语句执行顺序在select语句之后,所以要用select语句执行后的字段名

mysql> select
    -> stclass,max(stmath) as maxmath
    -> from
    -> t_student
    -> group by
    -> stclass
    -> having
    -> maxmath>90;
+---------+---------+
| stclass | maxmath |
+---------+---------+
| 1班     |      93 |
| 2班     |     100 |
+---------+---------+
2 rows in set (0.00 sec)

 方法二:先用where语句筛选出分数高于90分的,再用分组函数求各组的最高分

首先遍历全表筛选出高于90分的,第二次遍历时,只需要遍历第一次筛选出来的数据,效率较高!!!!

mysql> select
    -> stclass,
    -> max(stmath) as maxmath
    -> from
    -> t_student
    -> where
    -> stmath>90
    -> group by
    -> stclass;
+---------+---------+
| stclass | maxmath |
+---------+---------+
| 1班     |      93 |
| 2班     |     100 |
+---------+---------+
2 rows in set (0.00 sec)

limit      #查询结果截取

select  字段名  from 表名 limit  开始下标,截取长度;

开始下标不写默认从第一个开始!!!

下标从0开始limit书写顺序在最后执行顺序也是最后!!!

#查询数学成绩第5名到第10名

mysql> select
    -> stname,
    -> stmath
    -> from
    -> t_student
    -> order by
    -> stmath desc
    -> limit
    -> 4,5;
+--------+--------+
| stname | stmath |
+--------+--------+
| 前后   |     93 |
| 丙丁   |     91 |
| 秋     |     89 |
| 左右   |     88 |
| 甲乙   |     88 |
+--------+--------+
5 rows in set (0.00 sec)

union       合并查询结果集

将多条查询语句的结果进行合并,效率高于or语句

注!!!!!

结果集的列数和数据类型需要相同!!!

 例子:查询1班和2班的学生的班级、学号和姓名

法一:

select stclass,stno,stname from t_student where stclass='1班' or stclass='2班'; 

法二:

select stclass,stno,stname from t_student where stclass in ('1班','2班'); 

法三:

select stclass,stno,stname from t_student where stclass ='1班'      

union  

select stclass,stno,stname from t_student where stclass ='2班'; 


将查询结果放到一张新表里

create table 表名 as select.........

#将'1班'学生的数据存入class1中

mysql> create table class1 as select * from t_student where stclass ='1班';
Query OK, 9 rows affected (0.04 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> select * from class1;
+------+--------+-------+---------+--------+
| stno | stname | stsex | stclass | stmath |
+------+--------+-------+---------+--------+
| 5101 | 赵钱   | 男    | 1班     |     78 |
| 5103 | 上下   | 男    | 1班     |     47 |
| 5104 | 钱七   | 女    | 1班     |     93 |
| 5109 | 周三   | 女    | 1班     |     77 |
| 5114 | 张三   | 女    | 1班     |     87 |
| 5117 | 前后   | 女    | 1班     |     93 |
| 5119 | 春     | 女    | 1班     |     73 |
| 5121 | 冬     | 女    | 1班     |     54 |
| 5123 | 丙丁   | 男    | 1班     |     91 |
+------+--------+-------+---------+--------+
9 rows in set (0.00 sec)

 将查询结果插入到已经存在的表中

insert into 表名 select........;

#将2班的数据放到上面建好的class1表中

mysql> insert into class1 select * from t_student where stclass='2班';
Query OK, 9 rows affected (0.04 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> select * from class1;
+------+--------+-------+---------+--------+
| stno | stname | stsex | stclass | stmath |
+------+--------+-------+---------+--------+
| 5101 | 赵钱   | 男    | 1班     |     78 |
| 5103 | 上下   | 男    | 1班     |     47 |
| 5104 | 钱七   | 女    | 1班     |     93 |
| 5109 | 周三   | 女    | 1班     |     77 |
| 5114 | 张三   | 女    | 1班     |     87 |
| 5117 | 前后   | 女    | 1班     |     93 |
| 5119 | 春     | 女    | 1班     |     73 |
| 5121 | 冬     | 女    | 1班     |     54 |
| 5123 | 丙丁   | 男    | 1班     |     91 |
| 5105 | 李四   | 男    | 2班     |     43 |
| 5106 | 东西   | 男    | 2班     |     34 |
| 5107 | 左右   | 男    | 2班     |     88 |
| 5108 | 周一   | 男    | 2班     |     68 |
| 5110 | 周四   | 男    | 2班     |     94 |
| 5111 | 周日   | 男    | 2班     |     69 |
| 5113 | 赵六   | 男    | 2班     |     76 |
| 5118 | 周五   | 男    | 2班     |     99 |
| 5120 | 冷烬   | 男    | 2班     |    100 |
+------+--------+-------+---------+--------+
18 rows in set (0.00 sec)

 单表查询到此结束!!!!!

三、总结

查询语句书写顺序

select 
         ...        #查询的字段
from
         ...        #来自哪张表
where
        ...         #分组前筛选条件
group by
        ...         #按哪个字段分组
having
        ...          #分组后再次筛选
order by
        ...          #排序 (asc 升序,desc 降序)

limit              #截取查询结果

        ... 


执行顺序

1.from
2.where
3.group by
4.having
5.select
6.order by
7.limit

四、习题

问题描述:

找出各班男女生平均成绩,要求显示平均成绩高于73分的,2班除外,并按平均成绩降序输出。

mysql> select
    -> stclass,
    -> stsex,
    -> avg(stmath) as avgmath
    -> from
    -> t_student
    -> where
    -> stclass != '2班'
    -> group by
    -> stclass,stsex
    -> having
    -> avgmath>73
    -> order by
    -> avgmath desc;
+---------+-------+---------+
| stclass | stsex | avgmath |
+---------+-------+---------+
| 3班     | 男    | 81.5000 |
| 1班     | 女    | 79.5000 |
| 3班     | 女    | 74.8000 |
+---------+-------+---------+
3 rows in set (0.00 sec)

未完待续。。。。。。。。。。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷烬亿下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值