MySQL——四、SQL语句(下篇)

MySQL

  • 一、常见的SQL函数
    • 1、数学函数
    • 2、日期函数
    • 3、分组函数(聚合函数)
    • 4、流程控制函数
  • 二、where条件查询和order by排序
  • 三、分组统计
  • 四、多表关联查询
    • 1、交叉连接CROSS
    • 2、内连接inner
    • 3、外连接:outer
    • 4、子查询
  • 五、分页查询

一、常见的SQL函数

1、length(str):获取参数的字节数

  • a)length(): 单位是字节,utf8编码下,一个汉字三个字节,一个数字或字母一个字节。gbk编码下,一个汉字两个字节,一个数字或字母一个字节。
  • b)char_length():单位为字符,不管汉字还是数字或者是字母都算是一个字符。

注意: varchar(20)中的20表示字节数,如果存放utf-8编码的话只能放6个汉字。varchar(n),这里的n表示字节数。
MySQL 5.0.3 之后: varchar(20)表示字符数,不管什么编码,既汉字也能放20个。0-65532也就是最多占65532字节。
varchar(n)这里的n表示字符数,比如varchar(200),不管是英文还是中文都可以存放200个。

mysql> select length('abcd');
+----------------+
| length('abcd') |
+----------------+
|              4 |
+----------------+
1 row in set (0.00 sec)
mysql> select first_name,char_length(first_name) as '字符个数' from employees;
+-------------+--------------+
| first_name  | 字符个数     |
+-------------+--------------+
| Steven      |            6 |
| Neena       |            5 |
| Lex         |            3 |
| Alexander   |            9 |
| Bruce       |            5 |
mysql> select length('小白abc');
+---------------------+
| length('小白abc')   |
+---------------------+
|                   9 |
+---------------------+
1 row in set (0.00 sec)

2. concat(str1,str2,...):连接字符串

mysql> select concat(last_name,'--',first_name) as 姓名 from employees;

3. 字符串替换insertreplace

  • (1)insert(str1,x,len,'str2') 字串替换函数 str1返回的字串,字串字符的起始位置重1开始,当x为0值或负值(-2)时返回原始字符串;len是字串长度;str2是替换的字串
mysql> select insert(first_name,1,4,'000') from employees;
mysql> select insert('zhangsan',1,5,'li');
+-----------------------------+
| insert('zhangsan',1,5,'li') |
+-----------------------------+
| lisan                       |
+-----------------------------+
1 row in set (0.00 sec)
  • (2)replace(‘目标字符串’,‘被替换子串’,‘用于替换的新串’)替换
mysql> select replace('目标字符串','字符','哈哈');
+----------------------------------------------+
| replace('目标字符串','字符','哈哈')          |
+----------------------------------------------+
| 目标哈哈串                                   |
+----------------------------------------------+
1 row in set (0.00 sec)		

4、upper(str):小写字母变大写;lower(str):大写字母变小写;

mysql> select UPPER('hehe');
+---------------+
| upper('hehe') |
+---------------+
| HEHE          |
+---------------+
1 row in set (0.00 sec)
mysql> select lower('XIXI');
+---------------+
| lower('XIXI') |
+---------------+
| xixi          |
+---------------+
1 row in set (0.00 sec)

5.字符截取left right substr

  • (1)substr == substring SUBSTR(str,pos,len) 第一个数字是开始截取的索引值,第二个数数截取的长度
    • 案例:截取字符串,从第4个字符(包含)开始到最后
mysql> select substr('目标字符串',4) as out_put;
+---------+
| out_put |
+---------+
| 符串    |
+---------+
1 row in set (0.00 sec)
    • 案例:截取字符串,从第二个开始接到第三个
mysql> select substr('目标字符串',2,1) as out_put;
+---------+
| out_put |
+---------+
||
+---------+
1 row in set (0.00 sec)
  • (2)left('str1',4) 从左开始截取四个字符
  • (3)right('str1',4) 从右开始截取四个字符

6、trim 删除字符串左右两侧的空格,作用是去掉字符串前后的空格,中间空格去不掉

mysql> select trim('  hello world  ');
+-------------------------+
| trim('  hello world  ') |
+-------------------------+
| hello world             |
+-------------------------+
1 row in set (0.00 sec)

去掉前后两端的其他字符:

mysql> select trim('a' from 'abcasadefa'); 将a字符从指定的字符串中剔除(首和末尾)
+-----------------------------+
| trim('a' from 'abcasadefa') |
+-----------------------------+
| bcasadef                    |
+-----------------------------+
1 row in set (0.00 sec)

7.判断字符第一次出现的位置 instr locate

  • (1)instr(‘源字符串’,‘子字符串’):作用返回子字符串子源字符串里的起始索引.
mysql> select instr('目标字符串','字符');    //判断某字符在字符串中的第一次出现的位置
+--------------------------------------+
| instr('目标字符串','字符')           |
+--------------------------------------+
|                                    3 |
+--------------------------------------+
1 row in set (0.00 sec)

返回结果3, 如果找不到返回0

(2)mysql> select locate('a','dfdakfhsdf'); a字符在字符串中第一次出现的位置
+--------------------------+
| locate('a','dfdakfhsdf') |
+--------------------------+
|                        4 |
+--------------------------+
1 row in set (0.00 sec)

8.lpad字串填充
lpad(‘目标字符串’,10,‘填充字符’); 将填充字符填充到目标字符的左边,补足10个

mysql> select lpad('哈哈哈',10,'*');
+--------------------------+
| lpad('哈哈哈',10,'*')    |
+--------------------------+
| *******哈哈哈            |
+--------------------------+
1 row in set (0.00 sec)
mysql> select rpad('哈哈哈',10,'*');
+--------------------------+
| rpad('哈哈哈',10,'*')    |
+--------------------------+
| 哈哈哈*******            |
+--------------------------+
1 row in set (0.00 sec)

9.反显示字串 reverse

mysql> select reverse('dfdakfhsdf');
+-----------------------+
| reverse('dfdakfhsdf') |
+-----------------------+
| fdshfkadfd            |
+-----------------------+
1 row in set (0.00 sec)

10.比较两个字串顺序,strcmp如果这两个字符串相等返回0,如果第一个参数是根据当前的排序小于第二个参数顺序返回-1,否则返回1。

mysql> select strcmp('a','b')-> ;
+-----------------+
| strcmp('a','b') |
+-----------------+
|              -1 |
+-----------------+
1 row in set (0.00 sec)

11.正则匹配regexp

mysql> select first_name from employees where first_name regexp 'Su?an';  
+------------+
| first_name |
+------------+
| Susan      |
+------------+
1 row in set (0.00 sec)
?   前一个字符字符匹配 0 次或 1 次
^	字符串的开始
$	字符串的结尾
.	任何单个字符   .{3}
[. . . ]	在方括号内的字符列表
[^ . . . ]	非列在方括号内的任何字符
p1 | p2 | p3	交替匹配任何模式p1,p2或p3
*	零个或多个前面的元素
+	前面的元素的一个或多个实例
{n}	前面的元素的n个实例
{m , n}	m到n个实例前面的元素

char_length substr

1、数学函数

1.round 四舍五入

mysql> select round(1.45);
+-------------+
| round(1.45) |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)
mysql> select round(1.567,2);
+----------------+
| round(1.567,2) |
+----------------+
|           1.57 |
+----------------+
1 row in set (0.00 sec)

2.ceil 向上取整

mysql> select ceil(-1.3);
+------------+
| ceil(-1.3) |
+------------+
|         -1 |
+------------+
1 row in set (0.00 sec)
mysql> select ceil(1.3);
+-----------+
| ceil(1.3) |
+-----------+
|         2 |
+-----------+
1 row in set (0.00 sec)

3.floor 向下取整

mysql> select floor(1.3);
+------------+
| floor(1.3) |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)
mysql> select floor(-1.8);
+-------------+
| floor(-1.8) |
+-------------+
|          -2 |
+-------------+
1 row in set (0.00 sec)

4.truncate 截断小数点开始截取

mysql> select truncate(1.65,1);
+------------------+
| truncate(1.65,1) |
+------------------+
|              1.6 |
+------------------+
1 row in set (0.00 sec)
mysql> select truncate(1.6565,1);
+--------------------+
| truncate(1.6565,1) |
+--------------------+
|                1.6 |
+--------------------+
1 row in set (0.01 sec)
mysql> select truncate(1.6565,2);
+--------------------+
| truncate(1.6565,2) |
+--------------------+
|               1.65 |
+--------------------+
1 row in set (0.00 sec)

5.mod 取余

mysql> select mod(10,3);
+-----------+
| mod(10,3) |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

2、日期函数

1.now 用户返回当前日期时间

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-08-02 14:37:15 |
+---------------------+
1 row in set (0.00 sec)

2.curdate 返回当前系统日期,没有时间部分

mysql> select curdate();
+------------+
| curdate()  |
+------------+
| 2021-08-02 |
+------------+
1 row in set (0.00 sec)

3.curtime 返回当前系统时间,没有日期部分

mysql> select curtime();
+-----------+
| curtime() |
+-----------+
| 14:38:32  |
+-----------+
1 row in set (0.00 sec)

4.可以单独获取年/月/日

mysql> select year(now());
+-------------+
| year(now()) |
+-------------+
|        2021 |
+-------------+
1 row in set (0.00 sec)
mysql> select year('2021-1-1');
+------------------+
| year('2021-1-1') |
+------------------+
|             2021 |
+------------------+	
1 row in set (0.00 sec)
mysql> select month(now());
+--------------+
| month(now()) |
+--------------+
|            8 |
+--------------+
1 row in set (0.00 sec)
mysql> select day(now());
+------------+
| day(now()) |
+------------+
|          2 |
+------------+
1 row in set (0.00 sec)

hour minute second一样

5. 日期格式转换

mysql> select str_to_date('2021-08-02 10:20:30','%Y-%m-%d %H:%i:%s');
+--------------------------------------------------------+
| str_to_date('2021-08-02 10:20:30','%Y-%m-%d %H:%i:%s') |
+--------------------------------------------------------+
| 2021-08-02 10:20:30                                    |
+--------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select date_format(now(),'%y-%m-%d');
+-------------------------------+
| date_format(now(),'%y-%m-%d') |
+-------------------------------+
| 21-08-02                      |
+-------------------------------+
1 row in set (0.00 sec)

案例:查询入职日期是1992-4-3的员工信息:

mysql> select * from employees where hiredate='1992-4-3';
mysql> select * from employees where hiredate=STR_TO_DATE('1992 4 3','%Y %m %d');

3、分组函数(聚合函数)

分组函数和前面讲的函数不同在于,前面的对内容本身的处理,而分组函数的主要功能是统计
常用的分组函数sum , avg , max , min , count

mysql> select sum(salary) as 单月所发总工资 from employees;
+-----------------------+
| 单月所发总工资        |
+-----------------------+
|             691400.00 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select avg(salary) as 单月所发平均工资 from employees;
+--------------------------+
| 单月所发平均工资         |
+--------------------------+
|              6461.682243 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select max(salary) as 单月所发最多工资 from employees;
+--------------------------+
| 单月所发最多工资         |
+--------------------------+
|                 24000.00 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select min(salary) as 单月所发最少工资 from employees;
+--------------------------+
| 单月所发最少工资         |
+--------------------------+
|                  2100.00 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select count(*) as 总人数 from employees;
+-----------+
| 总人数    |
+-----------+
|       107 |
+-----------+
1 row in set (0.05 sec)
mysql> select count(salary) from employees;
+---------------+
| count(salary) |
+---------------+
|           107 |
+---------------+
1 row in set (0.00 sec)
mysql> select count(distinct salary) from employees;
+------------------------+
| count(distinct salary) |
+------------------------+
|                     57 |
+------------------------+
1 row in set (0.00 sec)

4、流程控制函数

1.if函数

mysql> select if('10>1','大','小');
+------------------------+
| if('10>1','大','小')   |
+------------------------+
||
+------------------------+
1 row in set, 1 warning (0.00 sec)

2.case函数

case 要判断的字段或表达式
when case的结果是常量1 then 要显示的值1(或语句1;)
when case的结果是常量2 then 要显示的值2(或语句2;)......
else case的结果都不前面的时候显示;
end 结束

案例:员工表中, 部门号是30,显示的工资是1.1倍
部门号是50,显示的工资是1.2倍
其他显示原工资

mysql> select salary as 原工资,department_id,-> case department_id-> when 30 then salary*1.1-> when 50 then salary*1.2-> else salary-> end as 新工资-> from employees;
+-----------+---------------+-----------+
| 原工资    | department_id | 新工资    |
+-----------+---------------+-----------+
|  24000.00 |            90 |  24000.00 |
|  17000.00 |            90 |  17000.00 |
|  17000.00 |            90 |  17000.00 |
|   9000.00 |            60 |   9000.00 |
|   6000.00 |            60 |   6000.00 |

3.多重if

case
when 条件1 then 要显示的值1(或语句1;)
when 条件2 then 要显示的值2(或语句2;)
......
else 前面的条件都不符合时候显示;
end 结束
mysql> select salary,-> case-> when salary>20000 then 'A级工资'-> when salary>10000 then 'B级工资'-> else 'C级工资'-> end as 工资等级-> from employees;
+----------+--------------+
| salary   | 工资等级     |
+----------+--------------+
| 24000.00 | A级工资      |
| 17000.00 | B级工资      |
| 17000.00 | B级工资      |

综合练习:
查询first_name字段字符长度小于字节长度的所有first_name;

mysql> select first_name,char_length(first_name) 
as '字符',length(first_name) as '字节' 
from  emp where 
char_length(first_name) < length(first_name);

二、where条件查询和order by排序

select column_name from table_Name;
select column_name from table_Name 
where 
group by
having
order by
limit  

where条件查询
语法 : select 查询列表 from 表名称 where 筛选条件
**按照条件表达式来筛选:**条件运算符: > , < , = , != / <>, >= , <=
按照逻辑表达式筛选逻辑运算符:and , not , or
模糊查询:% _ , like , between…and , in , is null ,is not null,regexp() .任意单个字符 * 匹配前一个字符任意次 ?匹配任意字符0或1次
条件表达式
案例:查询员工工资大于12000的员工有哪些?

mysql> select * from employees where salary > 12000;

案例:查询部门编号不等于90号的员工名和部门编号:

mysql> select concat(last_name,first_name) as 姓名, 
department_id 
from employees 
where department_id<>90;

逻辑表达式
案例:工资在10000到20000之间到员工名,工资和奖金

mysql> select last_name,salary,commission_pct 
from employees 
where salary>=10000 
and salary<=20000;

案例:查询部门编号不是在90到110之间的,或者工资高于15000的员工信息

mysql> select * from employees 
where department_id<90 or department_id>110
or salary>15000;
select * from employees  
where not(department_id<90 
and department_id>110)  
or salary>15000;

模糊查询:

like
between and
in
is null | is not null

like:
案例:查询员工名中包含了"a"字符的所有员工的信息

select * from employees where last_name like '%a%';

%:通配符,表示任意多个字符,也可表示0个字符,
_:任意一个字符;

案例:查询第三个字符为n或第五个字符为l的员工信息

mysql> select * from employees where last_name like '__n_l%';

案例:查询员工信息表中员工名第二个字符是"_"的员工信息

mysql> select * from employees where last_name like '_\_%';    _   \_
mysql> select * from employees where last_name like '_&_%' escape '&';  #推荐写法
escape '&':说明&这个符号是转义字符

between and:
案例:查询员工工资中10000到20000之间到员工信息

mysql> select * from employees where salary>=10000 and salary<=20000;
mysql> select * from employees where salary between 10000 and 20000;

注意: 使用between and

  • 1.可以简洁sql语句
  • 2.并且包含临界值
  • 3.临界值不能调换位置,小的在左边,大的值在右边.

in:(列表值)
案例:查询员工的工种编号是 it_prog,ad_vp,ad_pres中任意一个的员工信息

select * From employees 
where job_id='it_prog' 
or job_id='ad_vp' 
or job_id='ad_pres';select * from employees 
where job_id in ('it_prog','ad_vp','ad_pres');select * from employees 
where job_id Not in ('it_prog','ad_vp','ad_pres');select * from employees l
where job_id in ('it_prog','ad_vp','ad_pres',null);select * from employees 
where job_id not in ('it_prog','ad_vp','ad_pres',null);is null | is no null:

案例:查询没有奖金率的员工信息

mysql> select * from employees where commission_pct is null;

查询奖金率的就取反:

mysql> select * from employees where commission_pct is not null;

注意: commission_pct=null这个写法不能判断null值
is not也不能换成<>不等号.
<=>判断空值 is null

mysql> select * from employees where commission_pct <=>null;

排序查询
语法: select 查询列表 from 表 where 条件 order by 排序字段列表 asc | desc;
案例:查询所有员工信息,要求工资从大到小排列:

mysql> select * from employees order by salary desc;	
  • descend:降序
  • ascend:升序

反过来从小到大排列:

mysql> select * from employees order by salary asc;
mysql> select * from employees order by salary;   asc 可以省略,默认升序

案例:查询部门编号大于等于90的员工信息,按照入职时间的先后排序

mysql> select * from employees where department_id>=90 order by hiredate asc;

案例:实现按表达式排序:按年薪的高低显示员工信息

select last_name,department_id,salary*12*(1+ifnull(commission_pct,0)) as 年薪 
from employees 
order by salary*12*(1+ifnull(commission_pct,0)) desc;select  last_name,department_id,(salary+ifnull(commission_pct,0))*12 年薪 from employees
order  by (salary+ifnull(commission_pct,0))*12  desc;select *,salary*12*(1+ifnull(commission_pct,0)) as 年薪 
from employees 
order by 年薪 desc;

案例:使用函数来排序:按姓名的长度显示员工信息

mysql> select *,length(last_name) as 姓名的长度 from employees order by length(last_name) desc;
mysql> select *,length(last_name) as 姓名的长度 from employees order by 姓名的长度 desc;

案例:实现多字段排序:查询员工信息,首先用工资高低排序,工资一样的在按员工id大到小排序

mysql> select * from employees order by salary desc,employee_id desc;

查询employees表中所有员工的姓名以及薪资并将每人薪资+1000;
查询employees表显示每位员工薪资的位数;
注意: ceil()取整 或floor()
查询employees表中first_name和last_name连接显示并标记为’姓名’; concat

select concat(first_name,'-',last_name)  as 姓名 from employees;

查询员工表中的job_id类型有哪些;

select distinct job_id from employees;

查询每位员工电话号的后四位数字;

select right(phone_number,4) from employees;

三、分组统计

分组查询:
group by关键字实现分组,group by放在where条件语句之后,order by放置中group by的后面,后面跟上having关键字,总体的循序先后为:

where条件group by 分组语句having 分组的条件order by排序语句		

where条件是针对所有记录的,having条件只是局限的针对每一组的记录的
分组查询语法:

select(这个列要求必须只能是group by的后面字段),分组函数()
from表名
where筛选条件(针对表的所有记录)
group by分组字段列表
having(只能配合group by使用)与分组有关的筛选条件(针对分组后的每组内记录)
order by排序

案例:查询每个工种的最高工资

mysql> select max(salary),job_id from employees group by job_id;

案例:查询每个地方的部门个数

mysql> select count(*),location_id from departments group by location_id;

案例:查询每个部门每个工种的员工的平均工资

mysql> select count(*) 个数,avg(salary),department_id,job_id 
from employees 
group by department_id,job_id;

(部门号和工种号都相同的员工分一组)
案例:查询员工邮箱里包含"a"字母的,每个部门的平均工资

mysql> select avg(salary) 部门平均工资 , department_id 
from employees where email like '%a%' 
group by department_id;

案例:查询的有奖金的每个领导手下员工的最高工资

mysql> select max(salary) 最高工资 , manager_id 
from employees 
where commission_pct is not null 
group by manager_id

案例:查询部门的员工个数>5的,并显示所有部门的员工数

  • 1)查询每个部门的员工个数
mysql> select count(*) c,department_id 
from employees 
group by department_id;
  • 2)在第一步的结果中找那个部门的员工个数>5
mysql> select count(*) c,department_id 
from employees 
group by department_id 
having c>5;     (聚合函数的结果条件过滤)

案例:查询的没有奖金的每个领导手下员工的最高工资且最高工资工资大于12000,并且按升序排序。

  • 1)首先查询每个领导手下没有奖金的
mysql> select max(salary) 最高工资,manager_id 
from employees 
where commission_pct is null 
group by manager_id;
  • 2)在1点结果中在选工资大于12000
mysql> select max(salary) 最高工资,manager_id 
from employees 
where commission_pct is null 
group by manager_id 
having 最高工资>12000;
mysql> select max(salary) maxsalary,manager_id
from employees
where commission_pct is null
group by manager_id
having maxsalary>12000
order by maxsalary;

四、多表关联查询

1、交叉连接CROSS

将两张表或多张表联合起来查询,这就是连接查询。交叉连接返回的结果是被连接的两个表中所有数据行的笛卡儿积。
笛卡尔积是必须要知道的一个概念。在没有任何限制条件的情况下,两表连接必然会形成笛卡尔积。(如表1 m行a列,表2 n行b列,则无条件连接时则会有m*n,a+b列。)交叉连接查询在实际运用中没有任何意义
注意: 连接条件必须是唯一字段,如果非唯一字段则会产生笛卡尔积。

\>select * from 表1,表2;

2、内连接inner

指连接结果仅包含符合连接条件的行,参与连接的两个表都应该符合连接条件。

\>select * from 表1,表2 where  表1.字段=表2.字段;\>select * from employees e,departments d where e.department_id=d.department_id;
  • 1)等值连接:表之间用=连接
    案例:查询员工名和对应的部门名
mysql> select last_name,department_name 
from employees,departments 
where employees.department_id=departments.department_id;

可以使用别名

mysql> select last_name,department_name 
from employees e,departments d 
where e.department_id=d.department_id;

案例:查询有奖金的员工名以及所属部门名:

mysql> select last_name,department_name 
from employees e,departments d 
where e.department_id=d.department_id 
and e.commission_pct is not null;

案例:查询每个城市的部门个数

mysql> select count(*) as 个数 ,city 
from departments d,locations l 
where d.location_id=l.location_id 
group by city;

案例:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资

mysql> select d.department_name,d.manager_id,min(e.salary)
from departments d,employees e
where d.department_id = e.department_id
and e.commission_pct is not null
group by d.department_name,d.manager_id;

注意: sql中select后面的字段必须出现在group by后面,或者被聚合函数包裹,不然会抛出以下的错误
sql_mode=only_full_group_by
案例:查询每个工种的工种名和员工个数,并且按照员工个数排序降序

mysql> select job_title,count(*) 
from employees e,jobs j where e.job_id=j.job_id 
group by job_title 
order by count(*) desc;

案例:查询员工名,部门名和所在城市名

mysql> select last_name,department_name,city 
from employees e,departments d,locations l 
where e.department_id=d.department_id 
and d.location_id=l.location_id;
SELECT column_list
FROM t1
INNER JOIN t2 ON join_condition1
INNER JOIN t3 ON join_condition2
...
WHERE where_conditions;
  • 2)自连接:相当于等值连接,只不过是自己连接自己,不像等值连接是两个不同的表之间的;
    案例:查询员工名和他的上司的名字
mysql> select e.last_name,m.last_name 
from employees e,employees m 
where e.manager_id=m.employee_id;
  • 3)非等值连接:等值连接中的等号改成非等号情况

创建一张job_grades工资级别表:

create table job_grades(grade_level varchar(3),lowest_sal int,highest_sal int) ;
insert into job_grades values('A' , 1000,2999);
insert into job_grades values('B' , 3000,5999);
insert into job_grades values('C' , 6000,9999);
insert into job_grades values('D' , 10000,14999);
insert into job_grades values('E' , 15000,24999);
insert into job_grades values('F' , 25000,40000);

案例:查询员工的工资和工资级别

mysql> SELECT
salary,grade_level
FROM
employees e,job_grades j
WHERE
salary BETWEEN j.lowest_sal AND j.highest_sal;
select 查询列表
from 表1 别名
【链接类型】 join 表2 别名
on 链接条件
where 数据筛选条件;

1.查询员工名和其对应所属的部门名

select last_name,department_name
from employees e
inner join departments d
on e.department_id = d.department_id;

2.查询名字中包含e字母的员工名和其对象的部门名

select last_name,department_name
from employees e
inner join departments d
on e.department_id = d.department_id
where last_name like '%e%';

3.查询所在部门个数大于3的城市名和部门个数

select count(d.department_id) count,l.city
from departments d
inner join locations l
on d.location_id = l.location_id
group by l.city
having count>3;

4.查询员工个数大于3的部门名和员工个数,降序排序

SELECT d.department_name,COUNT(e.employee_id) c
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id
GROUP BY d.department_name
HAVING c>3
ORDER BY c DESC;

5.查询员工名以及对应的工种名和部门名,按部门名降序排序

select e.last_name,j.job_title,d.department_name
from employees e
inner join departments d
on e.department_id = d.department_id
inner join jobs j
on e.job_id=j.job_id
order by d.department_name desc;

案例:查询员工的工资和工资级别

SELECT
salary,grade_level
FROM
employees e
INNER JOIN
job_grades g
ON
e.salary BETWEEN g.lowest_sal AND g.highest_sal;

案例: 查询员工的名和其对应的直属领导

SELECT
e.last_name employee_name,
m.last_name manager_name
FROM
employees e
INNER JOIN
employees m
ON
e.manager_id=m.employee_id;

3、外连接:outer

外连不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。外连接分三类:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。
三者的共同点是都返回符合连接条件和查询条件(即:内连接)的数据行。不同点如下:

  • 左外连接还返回左表中不符合连接条件单符合查询条件的数据行。
  • 右外连接还返回右表中不符合连接条件单符合查询条件的数据行。
  • 全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即“全外=左外 UNION 右外”。

说明: 左表就是在“(LEFT OUTER JOIN)”关键字左边的表。右表当然就是右边的了。在三种类型的外连接中,OUTER 关键字是可省略的。
两张表:ta:id,age字段,tb:id,name,ta_id

create table ta(id int,age int);
create table tb(id int,name varchar(4),ta_id int);
insert into ta(id,age) values(1,12);
insert into ta(id,age) values(2,22);
insert into ta(id,age) values(3,32);
insert into ta(id,age) values(4,42);
insert into ta(id,age) values(5,52);
insert into ta(id,age) values(6,62);
insert into tb(id,name,ta_id) values(1,'任波涛',2);
insert into tb(id,name,ta_id) values(2,'田兴伟',1);
insert into tb(id,name,ta_id) values(3,'唐崇俊',3);
insert into tb(id,name,ta_id) values(4,'夏铭睿',8);
insert into tb(id,name,ta_id) values(5,'包琪',1);
insert into tb(id,name,ta_id) values(6,'夏雨',10);
insert into tb(id,name,ta_id) values(7,'夏铭雨',10);
insert into tb(id,name,ta_id) values(8,'白芳芳',6);

**外连接:**有这样的场景,在ta和tb两表中查询没有对应年龄数据的学生姓名和年龄

SELECT
tb.name,ta.age
FROM
tb
INNER JOIN
ta
ON
tb.ta_id=ta.id
WHERE
ta.id IS  NULL;

掌握外连接知识点:

  • 1.外连接的查询结果为主表中有的所有记录
    外表有对应数据,结果记录上显示对应数据
    外表中没有对应的数据,结果记录上填充null
    • 和内连接的区别:
    • 内连接: 当从表没有记录的时候,主、从表的记录都丢掉!
    • 外连接: 当从表没有记录的时候,会保留主表的记录,对应从表null
  • 2.左外连接:left join左边的是主表,右外连接right join 右边的是主表
  • 3.左外连接和右外连接上互通的所以掌握一个就好!

**解决:**在ta和tb两表中查询没有对应年龄数据的学生姓名和年龄

SELECT
tb.name,ta.age
FROM
tb
LEFT JOIN
ta
ON
tb.ta_id=ta.id
WHERE
ta.id IS NULL;

案例:查询没有员工的部门

SELECT d.department_id,d.department_name,e.employee_id
FROM departments d
LEFT JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id IS NULL;

全外连接: Oracle、MySQL不支持全连接。可以使用UNION ALL语句来组合左连接和右连接

4、子查询

子查询介绍: 出现在其他语句中的select语句,被包裹的select语句就是子查询或内查询
包裹子查询的外部的查询语句:称主查询语句
比如:

select last_name from employees
where department_id in(select department_id from departmentswhere location_id=1700
);

子查询分类
1、通过位置来分:

select 后面:仅仅支持标量子查询
from 后面:支持表子查询
where 或having 后面:支持标量子查询(重要)\列子查询(重要)\行子查询(用的较少)
exists 后面(相关查询):支持表子查询

2、按结果集的行列数不同分类:

标量子查询(结果集只有一行一列)
列子查询(结果集只有一列但有多行)
行子查询(结果集只有一行但有多列)
表子查询(结果集多行多列)

3、子查询特点:

子查询放在小括号内
子查询一般放在条件的右侧
标量子查询,一般搭配着单行操作符来使用(> < >= <= <> =)
列子查询,一般搭配着多行操作符使用:in any/some all
子查询的执行顺序优先于主查询(select后的子查询存在例外)
  • 1.where后面的标量子查询
    案例:查询工资比Abel这个人的高的员工信息
select * from employees
where salary>(
select salary
from employees
where last_name='Abel'
);
  • 2.查询job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
select last_name,job_id,salary
from employees
where job_id=(select job_id from employees
where employee_id=141 ) and salary>(select salary
from employees where employee_id=143);

(这个案例说明一个主查询里可以放很多个子查询)

  • 3.子查询里用到分组函数:查询公司工资最少的员工的last_name,job_id和salary
select last_name,job_id,salary 
from employees
where salary=(select min(salary) from employees);
  • 4.用到having的子查询:查询最低工资大于50号部门最低工资的部门id和其最低工资
select department_id , min(salary) from employees
group by department_id
having min(salary)>(select min(salary) from employees where department_id=50);
    1. where后面的列子查询(多行子查询)
首先来看一下多行操作符:in/not in:等于列表中的任意一个a in(10,20,30); 可以替换 a=10 or a=20 or a=30;	any/some:和子查询返回的某一个值比较a > any(10,20,30); 可以替换 a > min(10,20,30);all:和子查询返回的所有值比较a > all(10,20,30); 可以替换 a > max(10,20,30);a >10 and a>20 and a>30

案例:返回location_id是1400或1700的部门中的所有员工的名字

select last_name from employees
where department_id in (select department_id from departments
where location_id in (1400,1700));

案例:查询其他工种中比job_id为’IT_PROG’的员工某一工资低的员工的员工号,姓名,job_id和salary

SELECT employee_id,last_name,job_id,salary 
FROM employees
WHERE salary < ANY(SELECT distinct salary FROM employees WHERE job_id='IT_PROG') and job_id<>'IT_PROG';

案例:查询其他工种中比job_id为’IT_PROG’的员工所有工资低的员工的员工号,姓名,job_id和salary

SELECT employee_id,last_name,job_id,salary 
FROM employees
WHERE salary < all(SELECT distinct salary FROM employees WHERE job_id='IT_PROG') 
and job_id<>'IT_PROG';
    1. where后面的行子查询(一行多列)

案例:查询员工编号最小并且工资最高的员工信息

select * from employees
where
employee_id = (select min(employee_id) from employees)
and
salary = (select max(salary) from employees);

下面是行子查询的写法(用的很少,了解就可以):

select * from employees
where (employee_id,salary)=(
select min(employee_id) , max(salary) from employees
);
    1. select 后面(很少用的,可以用前面讲的方法实现):

案例:查询每个部门的部门信息和对应的员工个数(不用连接查询)

select d.*,(
select d.department_name count(*) from employees e
where d.department_id=e.department_id
) from departments d;select *,(select count(*) from employees e,departments dwhere d.department_id=e.department_id group by d.department_name ) temp
from departments temp;
    1. from后面的子查询:

案例:查询每个部门的平均工资等级

select avg(salary),department_id from employees group by department_id;SELECT
avg_res.avgs,avg_res.department_id,g.grade_level
FROM
(
SELECT AVG(salary) avgs,department_id
FROM employees GROUP BY department_id
) avg_res
,job_grades g
WHERE
avg_res.avgs BETWEEN g.lowest_sal AND g.highest_sal;
    1. exists后面(相关子查询)

exists的作用是: 判断子查询有没有结果的存在
案例: select exists(select employee_id from employees); 返回的结果:1;

语法:
select exists(完整的子查询); 子查询有结果返回1,没有结果返回0;
案例:查询有员工的部门名

select department_name from departments d
where exists(select * from employees e where d.department_id=e.department_id );

注意: 能用exists的绝对能用前面讲过的in来实现,所以exists很少使用

select department_name from departments d
where d.department_id in (
select department_id from employees
);

五、分页查询

分页查询:
数据记录条数过多的时候,需要分页来显示
语法:

select 查询字段 from 表名
where ....等等前面学过的所有写法
group by
having
order by
limit offset(开始记录索引,是从0开始的),size(要取出的条数);

案例: 查询前5条员工数据

mysql> select * from employees limit 0,5;
mysql> select * from employees limit 5;

注意: 如果从第一条开始,这个0可以省略:select * form employees limit 5;
案例:查询第11条到第25条

mysql> select * from employees limit 10,15;

案例:查询有奖金且工资最高的前10名的员工信息

select * from employees where commission_pct is not null order by salary desc limit 10;

分页查询的特点:
limit语句是位置上是要放在比order by语句的还后面,其次中sql执行过程中,limit也是最后去执行的语句.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/92956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【生物信息学】计算图网络中节点的中心性指标:聚集系数、介数中心性、度中心性

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. 生成邻接矩阵simulate_G: 2. 计算节点的聚集系数 CC(G): 3.计算节点的介数中心性 BC(G) 4. 计算节点的度中心性 DC(G) 5. 综合centrality(G) 6. 代…

第3章-指标体系与数据可视化-3.1.2-Seaborn绘图库

目录 3.1.2 Seaborn绘图库 1. 带核密度估计的直方图 2. 二元分布图 一维正态分布 联合分布

xilinx的原语的使用

xilinx的原语的使用 在学习FPGA实现千兆网时需要GMII转RGMII&#xff0c;这就涉及了原语的使用&#xff0c;特此记录&#xff01; 一、原语 与RGMII接口相关的原语&#xff1a; BUFG:全局时钟网络 BUFIO&#xff1a;只能采集IO的数据&#xff0c;采集IO数据的时候延时是最低的…

【【萌新的Risc-V学习之再看读不懂的流水线设计-10】】

萌新的Risc-V学习之再看读不懂的流水线设计-10 我们将流水线和之前案例中洗衣服的例子进行对照 我们把整个流水线分为5个阶段 也就是做成五级流水线 IF: 取指令ID: 指令译码和读寄存器堆EX: 执行或计算地址MEM: 数据存储器访问WB: 写回 我先在这里表述一下基本的几个指令的用…

四、cadence ic 617 ——添加工艺库文件

1.打开软件 linux界面与window不同,打开软件是由代码实现的。 打开软件时要在设定的工作区域打开,因为软件使用时会返回很多文件,在设定的工作区打开软件,这些文件就会返回到工作区域内。 输入ls回车,可以查询当前所在目录下的文件 输入cd+空格+文件名可以进入该文件 输…

【Java基础】抽象类和接口的使用

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习JavaSE的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、抽象类抽象类概念…

无设计经验也能制作专业国庆微传单

如果你正在计划一个国庆活动&#xff0c;或者想要创建一个微传单来宣传你的品牌或产品&#xff0c;那么你可以尝试使用乔拓云微传单平台。通过这个平台&#xff0c;你可以轻松地创建和发布一个精美的微传单&#xff0c;而且完全免费。 以下是制作国庆微传单H5的步骤&#xff1a…

react的组件

组件 组件是用来实现局部功能的代码和资源的集合&#xff08;html/css/js&#xff09;&#xff0c;用来复用代码。 react中分为函数式组件和类式组件。函数式组件就是一个函数&#xff0c;函数的返回值就是组件的视图内容。类式组件就是通过class关键字创建的类&#xff0c;类…

力扣每日一题(+日常水几题)

121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09;(很水) class Solution { public:int maxProfit(vector<int>& prices) {int ans 0;int pre prices[0];for(auto & x : prices){pre min(pre,x);ans max(ans, x - pre);}return ans;} }; 64…

stl格式-3D三角形

文章目录 什么是stl文件?格式首选stl的语法1.这是一个stl格式的文件:(ASCII码)2.下面先举个例子(难度略微提示)补充:关于\<\<我试了一下:这个法线你随便写好像也没问题\>> 3.来个立方体4.最后再写一个由三个直角形组成的立方体(直棱锥)5.amend 修正(右手定则,法线…

Java 多态

Java 多态 目录 Java 多态 实例 虚方法 多态是同一个行为具有多个不同表现形式或形态的能力。 多态性是对象多种表现形式的体现。 比如我们说"宠物"这个对象&#xff0c;它就有很多不同的表达或实现&#xff0c;比如有小猫、小狗、蜥蜴等等。那么我到宠物店说&q…

决策树剪枝:解决模型过拟合【决策树、机器学习】

如何通过剪枝解决决策树的过拟合问题 决策树是一种强大的机器学习算法&#xff0c;用于解决分类和回归问题。决策树模型通过树状结构的决策规则来进行预测&#xff0c;但在构建决策树时&#xff0c;常常会出现过拟合的问题&#xff0c;即模型在训练数据上表现出色&#xff0c;…

【ArcGIS Pro二次开发】(69):使用MapTool实现隐藏和隔离图层

一、MapTool简介 在ArcGIS Pro SDK中&#xff0c;MapTool是一个重要的组件&#xff0c;用于自定义地图操作工具&#xff0c;使用户能够在ArcGIS Pro中执行特定的地图交互操作。 在VS中添加新项&#xff0c;可以找到ArcGIS Pro 地图工具&#xff0c;即为MapTool。 新建后打开c…

HNU-CSer的推免经历记录

写在前面 本篇不是一个经验贴&#xff0c;不包含任何考核的具体内容。关于本校本年的推免情况&#xff0c;一些准备资料和我校主要推免到的学校的基本情况介绍我正在整理&#xff0c;后续完成后会放链接到这里&#xff08;也是因为一部分这个原因才决定写这一篇&#xff0c;同学…

站点信息搜集

站点信息搜集 1. whatweb 工具 kali自带的工具, 命令: whatweb httpbin.org http://httpbin.org [200 OK] Country[UNITED STATES][US], Email[mekennethreitz.org], HTML5, HTTPServer[gunicorn/19.9.0], IP[54.161.141.91], JQuery, Script[text/javascript], Title[ht…

javaee SpringMVC 乱码问题解决

方法一 在web.xml文件中注册过滤器 <!-- 注册过滤器 设置编码 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param&…

优雅的写Controller 层代码这样写才可以

前 言 本篇主要要介绍的就是controller层的处理&#xff0c;一个完整的后端请求由4部分组成&#xff1a; 接口地址(也就是URL地址)请求方式(一般就是get、set&#xff0c;当然还有put、delete)请求数据(request&#xff0c;有head跟body)响应数据(response) 本篇将解决以下3个…

Vue+element开发Simple Admin后端管理系统页面

最近看到各种admin&#xff0c;头大&#xff0c;内容太多&#xff0c;根本不知道怎么改。所以制作了这个项目&#xff0c;只包含框架、和开发中最常用的表格和表单&#xff0c;不用自己从头搭建架构&#xff0c;同时也容易上手二次开发。可以轻松从其他开源项目整合到本项目。项…

基于Qt Creator开发的坦克大战小游戏

目录 介绍开发环境技术介绍安装说明项目目录设计思想项目介绍运行演示知识点记录Gitee源码链接 介绍 &#xff01;&#xff01;&#xff01;资源图片是从网上免费下载&#xff0c;源码都是原创&#xff0c;供个人学习使用&#xff0c;非盈利&#xff01;&#xff01;&#xff…

UE5报错及解决办法

1、编译报错&#xff0c;内容如下&#xff1a; Unable to build while Live Coding is active. Exit the editor and game, or press CtrlAltF11 if iterating on code in the editor or game 解决办法 取消Enable Live Coding勾选