MySQL进阶(分组查询,多表连接查询)

目录

一 常见函数(单行函数)

二 分组函数

三 分组查询

四 多表连接查询

1.SQL99标准

1.1 内连接 

1.2外连接

1.3交叉连接

2.子查询

3 分页查询

4 联合查询


        接着上一期的数据库继续讲,上回我们说到简单的排序查询,接下来我们继续进阶,分组查询,多表连接查询。这篇博客基本都是知识点学起来比较枯燥,不过没办法为了挣钱,必须坚持下去。在学习分组查询之前不得不提到函数这个概念。因为分组查询常常是跟着分组函数联系起来的。

一 常见函数(单行函数)

在常见函数里,我把它分为字符函数,数学函数,日期函数,流程控制函数,其他函数,知识点挺多的,全是干货,大家一定要仔细学习。

字符函数:

    concat: 拼接
    substr: 截取子串
    upper: 转换成大写
    lower: 转换成小写
    trim: 去前后指定的空格和字符
    ltrim: 去左边空格
    rtrim: 去右边空格
    replace: 替换
    lpad: 左填充
    rpad: 右填充
    instr: 返回子串第一次出现的索引
    length: 获取字节个数    

1.length获取参数值得字节个数

 SELECT LENGTH('john');
==============================================================
2.concat 拼接字符串

 SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
================================================================
3.upper,lower 改变大小写

 SELECT UPPER('qweA');

 SELECT LOWER('GHUe');
实例:将姓变大写,名变小写,然后拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name))
FROM employees;

====================================================================
4.substr

注意:索引从一开始
截取从指定索引处开始后面所有的字符

 SELECT SUBSTR('李莫愁爱上了陆展元',7);

截取从指定索引处指定字符长度的字符

SELECT SUBSTR('李莫愁爱上了陆展元',1,3);

实例:姓名中首字母大写,其他字符小写
SELECT CONCAT( UPPER( SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)))
FROM employees;
===================================================================
5.instr 返回子串第一次出现的索引,找不到返回0

 SELECT INSTR('杨不悔殷六侠爱上殷六了殷六侠','殷六侠');
===============================================================
6.trim去前后空格,不去中间

 SELECT TRIM('     张翠山       ')
 SELECT TRIM('a' FROM 'aaaaaaaaaa张aaaa翠山aaaaaaa') qw
=================================================================
7.lpad 用指定字符实现左填充指定长度

  SELECT LPAD('殷素素',10,'*')
  SELECT LPAD('殷素素',2,'*')
=======================================================================
8.rpad 用指定字符实现右填充指定长度

      SELECT RPAD('殷素素',10,'*')
    
      SELECT RPAD('殷素素',12,'ab')
==========================================================================
9.replace

SELECT REPLACE('张无忌周芷若周若爱上了周芷若','周芷若','1' )

数学函数:

1.round 四舍五入
 SELECT ROUND(1.45)
 SELECT ROUND(1.456,2)
=============================
2.ceil 进一法,向上取整,>=
SELECT CEIL(1.52)   2
SELECT CEIL(-1.52)   -1
============================= 
3.floor 向下取整
 SELECT FLOOR(-9.99)   -10 
 SELECT FLOOR(1.52)  1
=============================
4.truncate 截断
SELECT TRUNCATE(1.65,1)   1.6
SELECT TRUNCATE(1.6999,1)  1.6

=============================
5.mod 取余
SELECT MOD(10,-3)
SELECT 10%3;

日期函数:

1.now 返回当前系统日期+时间
 SELECT NOW();

2.curdate 返回当前日期
 SELECT CURDATE()

3.curtime 返回当前时间
 SELECT CURTIME()

4.获取指定的部分,年,月,日,小时,分钟,秒
 SELECT YEAR(NOW()) 年

 SELECT MONTH(NOW()) 月

5.str_to_date 字符串转日期  
SELECT STR_TO_DATE('1998-3-4','%Y-%c-%d')

例子:查询入职日期为1992-4-3的员工信息
 
SELECT * FROM employees WHERE hiredate=STR_TO_DATE('4-3 1992','%c-%d %Y');


6.date_format 日期转字符 

SELECT DATE_FORMAT(NOW(),'%Y年%m月%d日')

流程控制函数:

1.if函数:
SELECT IF('10>5','大','小');

SELECT last_name,commission_pct ,IF(commission_pct IS NULL,'没','有')
FROM employees;

2.case函数:
使用一:swith case
case 字段或表达式 when 常量  then 要显示的值或语句

案例1:

 SELECT salary 原始,`department_id`,
 CASE `department_id`
 WHEN 30 THEN salary*1.1
 WHEN 40 THEN salary*1.2
 WHEN 50 THEN salary*1.3
 ELSE `salary`
 END AS 新工资
 FROM employees;

使用二:类似多重if
 case when 条件 then值1 else 值 end。

SELECT `salary`,CASE
WHEN `salary`>20000 THEN 'A'
WHEN `salary`>15000 THEN 'B'
ELSE 'C'
END 工资级别
FROM employees;

其它函数:

    version: 版本
    database: 当前库
    user: 当前连接用户

SELECT VERSION()

SELECT DATABASE()

SELECT USER()

二 分组函数

功能:统计使用,又称为统计函数,聚合函数,组函数分类:sum 求和,avg 平均值 ,max 最大值 ,min 最小值,count 计算个数、
特点:

1.sum,AVG 一般处理数值型
max,min count 都行
2.忽略null
3.可以和distinct搭配

1.简单使用:

SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

SELECT SUM(salary),COUNT(salary) FROM employees;

三 分组查询

 语法:

   select 查询的字段,分组函数
    from 表
    group by 分组的字段

特点:

    1、可以按单个字段分组
    2、和分组函数一同查询的字段最好是分组后的字段
    3、可以按多个字段分组,字段之间用逗号隔开
    4、可以支持排序
    5、having后可以支持别名

面试:

    * where 和 having 的区别?
        1. where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不                满足结果,则不会被查询出来
        2. where 后不可以跟聚合函数,having可以进行聚合函数的判断。

例子:

1.查询邮箱中包含a字符的,每个部门的平均工资

SELECT AVG(salary),`department_id`
FROM employees
WHERE email LIKE '%a%'
GROUP BY `department_id`

案例1.查询每个工种的工资

SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;

案例2:查询每个位置上的部门个数

 SELECT COUNT(*),location_id
 FROM `departments`
 GROUP BY `location_id`
 
 案例3.查询哪个部门的员工个数>2
 SELECT COUNT(*),`department_id`
 FROM employees
 GROUP BY `department_id`
 HAVING COUNT(*)>2
 
 案例4.查询每个工种有奖金的员工的最高工资>12000的员工编号,最高工资
 SELECT MAX(salary),`job_id`
 FROM employees
 GROUP BY `job_id`
 HAVING MAX(salary)>12000
 
 案例5.查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及最低工资
SELECT MIN(salary), `manager_id`
FROM employees
WHERE `manager_id`>102
GROUP BY `manager_id`
HAVING MIN(salary)>5000
 
#按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
SELECT COUNT(*),LENGTH(last_name)
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(*)>5

#按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),`department_id`,`job_id`
FROM employees
GROUP BY `department_id`,`job_id`

#添加排序

#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),`department_id`,`job_id`
FROM employees
WHERE `department_id` IS NOT NULL
GROUP BY `department_id`,`job_id`
HAVING AVG(salary)>10000
ORDER BY AVG(salary)

接下来来到下一个重点:多表连接查询

四 多表连接查询

 含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
 
笛卡尔乘积现象:表一 m行,表二 n行  结果:m*n行
解决办法:添加连接条件

分类:
    按年代分类:sql92,
            sql99【推荐】
            
            
    按功能分类:内连接:等值连接,非等值连接,自链接
                外连接:左外连接,右外连接,全外连接
                交叉连接

提到内连接,先了解了解笛卡尔集:

    * 产生条件:
        1. 省略连接条件
        2. 连接条件无效
        3. 所有表中所有行互相连接
    * 解决方案:
        添加有效筛选条件

1.SQL99标准

语法:

select 查询列表  from 表1 别名【连接类型】
    join 表2 别名
    on 连接条件
    【where 筛选条件】
    【group by 】
    【having 】
    【order by】


特点:
 
   筛选条件放在where后面,如like
    
分类:    
    内连接:inner
    外连接:左外连接:left【outer】
                  右外连接:right【outer】
                  全外连接:full【outer】
    交叉连接:cross  
 
    

1.1 内连接 

	select 查询列表
	from 表1 别名【inner】
	join 表2 别名
	on 连接条件


   

内连接分类:等值连接,非等值,自连接

接下来通过几个案例讲解一下:

1.等值连接
===================================================================
/*①案例1:查询员工名,部门名。*/
 SELECT `last_name`,`department_name`
 FROM employees e
 JOIN departments d
 ON e.`department_id` = d.`department_id`;


================================================================
/*②案例2:查询部门个数>3的城市名和部门个数,(添加分组,筛选)*/
SELECT `city`,COUNT(*)
FROM `locations` l
INNER JOIN `departments` d
ON l.`location_id`=d.`location_id`
GROUP BY `city`
HAVING COUNT(*)>3;
====================================================================
/*③案例3:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)*/
SELECT COUNT(*),`department_name`
FROM `departments` d
INNER JOIN `employees` e
ON d.`department_id`=e.`department_id`
GROUP BY d.`department_name`
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;

========================================================================
========================================================================
2.非等值连接

/*查询员工的工资级别*/

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

===========================================================================

3.自连接
/*查询员工名,上级名*/

SELECT e.`last_name`,m.`last_name`
FROM `employees` e
JOIN employees m
ON e.`manager_id`=m.`employee_id`


这几个案例讲解的就是内连接。然后讲解外连接。

1.2外连接

应用场景:用于查询一个表中有,宁一个表中没有的记录

特点:
1.外连接的查询结果为主表的所有记录
如果从表中有和他匹配的,则显示匹配的值
如果从表中没有和他匹配的,则显示null

2.左外连接,left左边的是主表
  右外连接,right右边的是主表

还是通过一个案例,便于理解:

查询哪个部门没有员工

1.左外
SELECT d.*,e.`employee_id`
FROM `departments` d
LEFT OUTER JOIN `employees` e
ON d.`department_id`=e.`department_id`
WHERE e.`employee_id` IS NULL;


2.右外

SELECT d.*,e.`employee_id`
FROM  employees e
RIGHT OUTER JOIN`departments` d
ON d.`department_id`=e.`department_id`
WHERE e.`employee_id` IS NULL;

3.全外连接
USE girls;
SELECT b.*,bo.*
FROM`beauty` b
FULL OUTER `boys` bo
ON b.`id`=bo.`id`

1.3交叉连接

交叉连接
SELECT b.*,bo.*

FROM`beauty` b
CROSS JOIN boys bo

下一个重难点:子查询

2.子查询

含义:出现在其他语句中的select语句,称为子查询或内查询,外部的查询语句,称为主查询或外查询
分类:
1.按子查询出现的位置:
        select后面  标量子查询
        from后面   表子查询
        ※※where,having  标量子查询(单行)√  列子查询(多行)√  行子查询
        exists(相关子查询)表子查询
2.按结果集的`department_id`行列数不同:
        标量子查询(结果集只有一行一列)
        列子查询(结果集只有一列多行)
        行子查询(结果集只有一行多列)
        表子查询(结果集一般为多行多列)
      

特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配单行操作符
><=
列子查询,一般搭配多行操作符
in,any/some/all

4.子查询优先于主查询

1.标量子查询

/*案例一:谁的工资比abel高*/
SELECT *
FROM employees
WHERE salary >(
SELECT salary
FROM employees
WHERE last_name = 'Abel'

)

案例二:查询job——ID与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
SELECT *
FROM employees
WHERE job_id = (
SELECT job_id
FROM employees
WHERE `employee_id`=141
) AND salary>(
SELECT salary
FROM employees
WHERE `employee_id`=143

2.列子查询

案例:查询`location_id`是1400或者1700的部门中所有员工姓名
SELECT `last_name`
FROM employees
WHERE `department_id` IN(

SELECT DISTINCT `department_id`
FROM `departments`
WHERE `location_id` IN (1400,1700
)
)


查询其他部门中比job_id为‘IT_PROG’部门任一工资低的员工的,工号,姓名,job_id,salary


SELECT `employee_id`,`last_name`,`salary`
FROM employees
WHERE salary < ANY(
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
)AND job_id<>'IT_PROG'

放在exists后面(相关子查询)

语法:exists(完整查询语句)
结果0,1

SELECT EXISTS(SELECT `employee_id`FROM `employees` WHERE salary=300000)

/*查询有员工的部门名*/

SELECT `department_name`
FROM `departments` d
WHERE EXISTS (
SELECT * FROM employees e
WHERE d.`department_id`=e.`department_id`
)


3 分页查询

语法:

	select 字段|表达式,...
	from 表
	where 条件
	group by 分组字段
	having 条件
	order by 排序的字段
	limit 起始的条目索引,条目数;

特点:

    1.起始条目索引从0开始

    2.limit子句放在查询语句的最后

    3.公式:select * from  表 limit (page-1)*sizePerPage,sizePerPage
    假如:
        每页显示条目数sizePerPage
        要显示的页数 page

查询前五条
SELECT *
FROM employees
LIMIT 0,5

4 联合查询

语法:

	select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
	select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
	select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
	.....
	select 字段|常量|表达式|函数 from 表 where 条件

特点:

    1、多条查询语句的查询的列数必须是一致的
    2、多条查询语句的查询的列的类型几乎相同
    3、union代表去重,union all代表不去重

代码:

/*查询部门编号>90或者邮箱包含a的员工信息
*/
SELECT *
FROM employees
WHERE email LIKE'%a%'
UNION

SELECT *
FROM employees
WHERE `department_id`>90

你可能感兴趣的:(mysql,数据库,sql)