MySQL基础:基础查询

DQL语言:数据查询语言

3.1 基础查询

语法java

select 查询列表
from 表名;

特色mysql

查询列表能够是字段、常量、表达式、函数,也能够是多个
查询结果是一个虚拟表

示例sql

一、查询单个字段
select 字段名 from 表名;

二、查询多个字段
select 字段名,字段名 from 表名;

三、查询全部字段
select * from 表名

四、查询常量
select 常量值;
注意:字符型和日期型的常量值必须用单引号引发来,数值型不须要

五、查询函数
select 函数名(实参列表);

六、查询表达式
select 100/1234;

七、起别名
①as
②空格

八、去重
select distinct 字段名 from 表名;

九、+
做用:作加法运算
select 数值+数值; 直接运算
select 字符+数值;先试图将字符转换成数值,若是转换成功,则继续运算;不然转换成0,再作运算
select null+值;结果都为null

十、【补充】concat函数
功能:拼接字符
select concat(字符1,字符2,字符3,...);

十一、【补充】ifnull函数
功能:判断某字段或表达式是否为null,若是为null 返回指定的值,不然返回本来的值
select ifnull(commission_pct,0) from employees;

十二、【补充】isnull函数
功能:判断某字段或表达式是否为null,若是是,则返回1,不然返回0

基础查询的示例:数据库

#进阶1:基础查询
/*
语法:
select 查询列表 from 表名;


相似于:System.out.println(打印东西);

特色:

一、查询列表能够是:表中的字段、常量值、表达式、函数
二、查询的结果是一个虚拟的表格
*/

USE myemployees;

#1.查询表中的单个字段

SELECT last_name FROM employees;

#2.查询表中的多个字段
SELECT last_name,salary,email FROM employees;

#3.查询表中的全部字段

#方式一:
SELECT 
    `employee_id`,
    `first_name`,
    `last_name`,
    `phone_number`,
    `last_name`,
    `job_id`,
    `phone_number`,
    `job_id`,
    `salary`,
    `commission_pct`,
    `manager_id`,
    `department_id`,
    `hiredate` 
FROM
    employees ;
#方式二:  
 SELECT * FROM employees;
 
 #4.查询常量值
 SELECT 100;
 SELECT 'john';
 
 #5.查询表达式
 SELECT 100%98;
 
 #6.查询函数
 
 SELECT VERSION();
 
 
 #7.起别名
 /*
 ①便于理解
 ②若是要查询的字段有重名的状况,使用别名能够区分开来
 
 */
 #方式一:使用as
SELECT 100%98 AS 结果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;

#方式二:使用空格
SELECT last_name 姓,first_name 名 FROM employees;


#案例:查询salary,显示结果为 out put
SELECT salary AS "out put" FROM employees;


#8.去重


#案例:查询员工表中涉及到的全部的部门编号
SELECT DISTINCT department_id FROM employees;


#9.+号的做用

/*

java中的+号:
①运算符,两个操做数都为数值型
②链接符,只要有一个操做数为字符串

mysql中的+号:
仅仅只有一个功能:运算符

select 100+90; 两个操做数都为数值型,则作加法运算
select '123'+90;只要其中一方为字符型,试图将字符型数值转换成数值型
			若是转换成功,则继续作加法运算
select 'john'+90;	若是转换失败,则将字符型数值转换成0

select null+10; 只要其中一方为null,则结果确定为null

*/

#案例:查询员工名和姓链接成一个字段,并显示为 姓名


SELECT CONCAT('a','b','c') AS 结果;

SELECT 
	CONCAT(last_name,first_name) AS 姓名
FROM
	employees;

3.2 条件查询

语法安全

select 查询列表
from 表名
where 筛选条件

筛选条件的分类服务器

一、简单条件运算符
> < = <> != >= <=    <=>安全等于

二、逻辑运算符
 && and
  || or
  !  not
  
三、模糊查询
 like:通常搭配通配符使用,能够判断字符型或数值型
 通配符:%任意多个字符,_任意单个字符

between and
in
is null /is not null:用于判断null值

is null PK <=>
			普通类型的数值	null值		可读性
is null		×			√		√
<=>		√			√		×

条件查询的示例markdown

#进阶2:条件查询
/*

语法:
	select 
		查询列表
	from
		表名
	where
		筛选条件;

分类:
	1、按条件表达式筛选
	
	简单条件运算符:> < = != <> >= <=
	
	2、按逻辑表达式筛选
	逻辑运算符:
	做用:用于链接条件表达式
		&& || !
		and or not
		
	&&和and:两个条件都为true,结果为true,反之为false
	||或or: 只要有一个条件为true,结果为true,反之为false
	!或not: 若是链接的条件自己为false,结果为true,反之为false
	
	3、模糊查询
		like
		between and
		in
		is null
	
*/
#1、按条件表达式筛选

#案例1:查询工资>12000的员工信息

SELECT 
	*
FROM
	employees
WHERE
	salary>12000;
	
	
#案例2:查询部门编号不等于90号的员工名和部门编号
SELECT 
	last_name,
	department_id
FROM
	employees
WHERE
	department_id<>90;


#2、按逻辑表达式筛选

#案例1:查询工资z在10000到20000之间的员工名、工资以及奖金
SELECT
	last_name,
	salary,
	commission_pct
FROM
	employees
WHERE
	salary>=10000 AND salary<=20000;
#案例2:查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT
	*
FROM
	employees
WHERE
	NOT(department_id>=90 AND  department_id<=110) OR salary>15000;
#3、模糊查询
/*
like

	
	
between and
in
is null|is not null

*/
#1.like
/*
特色:
①通常和通配符搭配使用
	通配符:
	% 任意多个字符,包含0个字符
	_ 任意单个字符
*、

#案例1:查询员工名中包含字符a的员工信息

select 
	*
from
	employees
where
	last_name like '%a%';#abc
#案例2:查询员工名中第三个字符为e,第五个字符为a的员工名和工资
select
	last_name,
	salary
FROM
	employees
WHERE
	last_name LIKE '__n_l%';



#案例3:查询员工名中第二个字符为_的员工名

SELECT
	last_name
FROM
	employees
WHERE
	last_name LIKE '_$_%' ESCAPE '$';
#2.between and
/*
①使用between and 能够提升语句的简洁度
②包含临界值
③两个临界值不要调换顺序

*/


#案例1:查询员工编号在100到120之间的员工信息

SELECT
	*
FROM
	employees
WHERE
	employee_id >= 120 AND employee_id<=100;
#----------------------
SELECT
	*
FROM
	employees
WHERE
	employee_id BETWEEN 120 AND 100;

#3.in
/*
含义:判断某字段的值是否属于in列表中的某一项
特色:
	①使用in提升语句简洁度
	②in列表的值类型必须一致或兼容
	③in列表中不支持通配符
	

*/
#案例:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号

SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id = 'IT_PROT' OR job_id = 'AD_VP' OR JOB_ID ='AD_PRES';


#------------------

SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id IN( 'IT_PROT' ,'AD_VP','AD_PRES');

#四、is null
/*
=或<>不能用于判断null值
is null或is not null 能够判断null值




*/

#案例1:查询没有奖金的员工名和奖金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NULL;


#案例1:查询有奖金的员工名和奖金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NOT NULL;

#----------如下为×
SELECT
	last_name,
	commission_pct
FROM
	employees

WHERE 
	salary IS 12000;
	
	
#安全等于  <=>


#案例1:查询没有奖金的员工名和奖金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct <=>NULL;
	
	
#案例2:查询工资为12000的员工信息
SELECT
	last_name,
	salary
FROM
	employees

WHERE 
	salary <=> 12000;
	

#is null pk <=>

IS NULL:仅仅能够判断NULL值,可读性较高,建议使用
<=>    :既能够判断NULL值,又能够判断普通的数值,可读性较低

3.3 排序查询

语法oracle

select 查询列表
from 表
where 筛选条件
order by 排序列表 【asc}desc】

特色函数

asc :升序,若是不写默认升序
   desc:降序

排序列表 支持 单个字段、多个字段、函数、表达式、别名

order by的位置通常放在查询语句的最后(除limit语句以外)

3.4 常见函数

概述sqlserver

功能:相似于java中的方法
好处:提升重用性和隐藏实现细节
调用:select 函数名(实参列表);

单行函数

一、字符函数
  concat:链接
  substr:截取子串
  upper:变大写
  lower:变小写
  replace:替换
  length:获取字节长度
  trim:去先后空格
  lpad:左填充
  rpad:右填充
  instr:获取子串第一次出现的索引
  
二、数学函数
  ceil:向上取整
  round:四舍五入
  mod:取模
  floor:向下取整
  truncate:截断
  rand:获取随机数,返回0-1之间的小数

三、日期函数
  now:返回当前日期+时间
  year:返回年
  month:返回月
  day:返回日
  date_format:将日期转换成字符
  curdate:返回当前日期
  str_to_date:将字符转换成日期
  curtime:返回当前时间
  hour:小时
  minute:分钟
  second:秒
  datediff:返回两个日期相差的天数
  monthname:以英文形式返回月


四、其余函数
  version 当前数据库服务器的版本
  database 当前打开的数据库
  user当前用户
  password('字符'):返回该字符的密码形式
  md5('字符'):返回该字符的md5加密形式


五、流程控制函数
  ①if(条件表达式,表达式1,表达式2):若是条件表达式成立,返回表达式1,不然返回表达式2
  ②case状况1
  case 变量或表达式或字段
  when 常量1 then 值1
  when 常量2 then 值2
  ...
  else 值n
  end
  ③case状况2
  case 
  when 条件1 then 值1
  when 条件2 then 值2
  ...
  else 值n
  end

单行函数的示例:

#进阶4:常见函数

/*

概念:相似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
好处:一、隐藏了实现细节  二、提升代码的重用性
调用:select 函数名(实参列表) 【from 表】;
特色:
	①叫什么(函数名)
	②干什么(函数功能)

分类:
	一、单行函数
	如 concat、length、ifnull等
	二、分组函数
	
	功能:作统计使用,又称为统计函数、聚合函数、组函数
	
常见函数:
	1、单行函数
	字符函数:【mysql中字符下标从1开始】
	length:获取字节个数(utf-8一个汉字表明3个字节,gbk为2个字节)
	concat:字段、字符链接
	substr:字符串截取,三个参数(截什么,从哪里开始,截几个)
	instr :返回子串第一次出现的索引,若是找不到返回0
	trim : 去首尾空格,也可去除自定字符
	upper :转大写
	lower :转小写
	lpad  :用指定的字符实现左填充指定长度
	rpad  :用指定的字符实现右填充指定长度
	replace:替换,三个参数(须要替换的字符串,原字符串,目标字符串)
	
	数学函数:
	round:四舍五入
	ceil:向上取整,返回>=该参数的最小整数
	floor:向下取整,返回<=该参数的最大整数
	truncate:截取小数后几位
	mod :取余
	
	日期函数:
	now:返回当前系统日期+时间
	curdate:返回当前系统日期,不包含时间
	curtime:返回当前时间,不包含日期
	year
	month
	monthname
	day
	hour
	minute
	second
	str_to_date:将字符经过指定的格式转换成日期
	date_format:将日期转换成字符
	
	其余函数:
	version :查看mysql版本号
	database :查看数据库
	user	:查看当前用户
	控制函数
	if: 三个参数,相似三元表达式
	case:多种状况,相似switch case

*/


#1、字符函数

#1.length 获取参数值的字节个数
SELECT LENGTH('john');
SELECT LENGTH('张三丰hahaha');

SHOW VARIABLES LIKE '%char%'

#2.concat 拼接字符串

SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;

#3.upper、lower
SELECT UPPER('john');
SELECT LOWER('joHn');
#示例:将姓变大写,名变小写,而后拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name))  姓名 FROM employees;

#4.substr、substring
注意:索引从1开始
#截取从指定索引处后面全部字符
SELECT SUBSTR('李莫愁爱上了陆展元',7)  out_put;

#截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了陆展元',1,3) out_put;


#案例:姓名中首字符大写,其余字符小写而后用_拼接,显示出来

SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)))  out_put
FROM employees;

#5.instr 返回子串第一次出现的索引,若是找不到返回0

SELECT INSTR('杨不殷六侠悔爱上了殷六侠','殷八侠') AS out_put;

#6.trim

SELECT LENGTH(TRIM('    张翠山    ')) AS out_put;

SELECT TRIM('aa' FROM 'aaaaaaaaa张aaaaaaaaaaaa翠山aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')  AS out_put;

#7.lpad 用指定的字符实现左填充指定长度

SELECT LPAD('殷素素',2,'*') AS out_put;

#8.rpad 用指定的字符实现右填充指定长度

SELECT RPAD('殷素素',12,'ab') AS out_put;


#9.replace 替换

SELECT REPLACE('周芷若周芷若周芷若周芷若张无忌爱上了周芷若','周芷若','赵敏') AS out_put;



#2、数学函数

#round 四舍五入
SELECT ROUND(-1.55);
SELECT ROUND(1.567,2);


#ceil 向上取整,返回>=该参数的最小整数

SELECT CEIL(-1.02);

#floor 向下取整,返回<=该参数的最大整数
SELECT FLOOR(-9.99);

#truncate 截断

SELECT TRUNCATE(1.69999,1);

#mod取余
/*
mod(a,b) :  a-a/b*b

mod(-10,-3):-10- (-10)/(-3)*(-3)=-1
*/
SELECT MOD(10,-3);
SELECT 10%3;


#3、日期函数

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

#curdate 返回当前系统日期,不包含时间
SELECT CURDATE();

#curtime 返回当前时间,不包含日期
SELECT CURTIME();


#能够获取指定的部分,年、月、日、小时、分钟、秒
SELECT YEAR(NOW()) 年;
SELECT YEAR('1998-1-1') 年;

SELECT  YEAR(hiredate) 年 FROM employees;

SELECT MONTH(NOW()) 月;
SELECT MONTHNAME(NOW()) 月;


#str_to_date 将字符经过指定的格式转换成日期

SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;

#查询入职日期为1992--4-3的员工信息
SELECT * FROM employees WHERE hiredate = '1992-4-3';

SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');


#date_format 将日期转换成字符

SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;

#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') 入职日期
FROM employees
WHERE commission_pct IS NOT NULL;


#4、其余函数

SELECT VERSION();
SELECT DATABASE();
SELECT USER();


#5、流程控制函数
#1.if函数: if else 的效果

SELECT IF(10<5,'大','小');

SELECT last_name,commission_pct,IF(commission_pct IS NULL,'没奖金,呵呵','有奖金,嘻嘻') 备注
FROM employees;




#2.case函数的使用一: switch case 的效果

/*
java中
switch(变量或表达式){
	case 常量1:语句1;break;
	...
	default:语句n;break;


}

mysql中

case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
*/

/*案例:查询员工的工资,要求

部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其余部门,显示的工资为原工资

*/


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;



#3.case 函数的使用二:相似于 多重if
/*
java中:
if(条件1){
	语句1;
}else if(条件2){
	语句2;
}
...
else{
	语句n;
}

mysql中:

case 
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
。。。
else 要显示的值n或语句n
end
*/

#案例:查询员工的工资的状况
若是工资>20000,显示A级别
若是工资>15000,显示B级别
若是工资>10000,显示C级别
不然,显示D级别


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

分组函数

一、分类
 max 最大值
 min 最小值
 sum 和
 avg 平均值
 count 计算个数

 二、特色

 ①语法
 select max(字段) from 表名;

 ②支持的类型
 sum和avg通常用于处理数值型
 max、min、count能够处理任何数据类型

 ③以上分组函数都忽略null
 ④均可以搭配distinct使用,实现去重的统计
 select sum(distinct 字段) from 表;
 ⑤count函数
 count(字段):统计该字段非空值的个数
 count(*):统计结果集的行数
 案例:查询每一个部门的员工个数
 1 xx    10
 2 dd    20
 3 mm    20
 4 aa    40
 5 hh    40

 count(1):统计结果集的行数

 效率上:
 MyISAM存储引擎,count(*)最高
 InnoDB存储引擎,count(*)和count(1)效率>count(字段)

 ⑥ 和分组函数一同查询的字段,要求是group by后出现的字段

分组函数实例

#2、分组函数
/*
功能:用做统计使用,又称为聚合函数或统计函数或组函数

分类:
sum 求和、avg 平均值、max 最大值 、min 最小值 、count 计算个数(非空)

特色:
一、sum、avg通常用于处理数值型
   max、min、count能够处理任何类型
二、以上分组函数都忽略null值

三、能够和distinct搭配实现去重的运算

四、count函数的单独介绍
通常使用count(*)用做统计行数

五、和分组函数一同查询的字段要求是group by后的字段

*/


#一、简单 的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;


SELECT SUM(salary) 和,AVG(salary) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM employees;

SELECT SUM(salary) 和,ROUND(AVG(salary),2) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM employees;

#二、参数支持哪些类型

SELECT SUM(last_name) ,AVG(last_name) FROM employees; #没有意义
SELECT SUM(hiredate) ,AVG(hiredate) FROM employees;#可排序便可求和

SELECT MAX(last_name),MIN(last_name) FROM employees;

SELECT MAX(hiredate),MIN(hiredate) FROM employees;

SELECT COUNT(commission_pct) FROM employees;
SELECT COUNT(last_name) FROM employees;

#三、SUM、AVG等会忽略null,由于执行结果没有null,null+任何值都为null

SELECT SUM(commission_pct) ,AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;

SELECT MAX(commission_pct) ,MIN(commission_pct) FROM employees;

SELECT COUNT(commission_pct) FROM employees;
SELECT commission_pct FROM employees;


#四、和distinct搭配

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

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



#五、count函数的详细介绍

SELECT COUNT(salary) FROM employees;

SELECT COUNT(*) FROM employees;

SELECT COUNT(1) FROM employees;

效率:
MYISAM存储引擎下  ,COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差很少,比COUNT(字段)要高一些


#六、和分组函数一同查询的字段有限制

SELECT AVG(salary),employee_id  FROM employees;

3.5 分组查询

语法

select 分组函数,分组后的字段
from 表
【where 筛选条件】
group by 分组的字段
【having 分组后的筛选】
【order by 排序列表】

特色

使用关键字		筛选的表	位置
		分组前筛选		where		原始表			group by的前面
  		分组后筛选		having		分组后的结果	  group by 的后面

分组函数示例

#2、分组函数
/*
功能:用做统计使用,又称为聚合函数或统计函数或组函数

分类:
sum 求和、avg 平均值、max 最大值 、min 最小值 、count 计算个数(非空)

特色:
一、sum、avg通常用于处理数值型
   max、min、count能够处理任何类型
二、以上分组函数都忽略null值

三、能够和distinct搭配实现去重的运算

四、count函数的单独介绍
通常使用count(*)用做统计行数

五、和分组函数一同查询的字段要求是group by后的字段

*/


#一、简单 的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;


SELECT SUM(salary) 和,AVG(salary) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM employees;

SELECT SUM(salary) 和,ROUND(AVG(salary),2) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM employees;

#二、参数支持哪些类型

SELECT SUM(last_name) ,AVG(last_name) FROM employees; #没有意义
SELECT SUM(hiredate) ,AVG(hiredate) FROM employees;#可排序便可求和

SELECT MAX(last_name),MIN(last_name) FROM employees;

SELECT MAX(hiredate),MIN(hiredate) FROM employees;

SELECT COUNT(commission_pct) FROM employees;
SELECT COUNT(last_name) FROM employees;

#三、SUM、AVG等会忽略null,由于执行结果没有null,null+任何值都为null

SELECT SUM(commission_pct) ,AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;

SELECT MAX(commission_pct) ,MIN(commission_pct) FROM employees;

SELECT COUNT(commission_pct) FROM employees;
SELECT commission_pct FROM employees;


#四、和distinct搭配

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

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



#五、count函数的详细介绍

SELECT COUNT(salary) FROM employees;

SELECT COUNT(*) FROM employees;

SELECT COUNT(1) FROM employees;

效率:
MYISAM存储引擎下  ,COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差很少,比COUNT(字段)要高一些


#六、和分组函数一同查询的字段有限制

SELECT AVG(salary),employee_id  FROM employees;

分组查询示例

#进阶5:分组查询,当条件在另外一个表中就须要分组查询group by

/*
语法:

select 查询列表
from 表
【where 筛选条件】
group by 分组的字段
【order by 排序的字段】;

特色:
一、和分组函数一同查询的字段必须是group by后出现的字段
二、筛选分为两类:分组前筛选和分组后筛选
		
			针对的表				位置			  链接的关键字
分组前筛选	原始表					group by前		  where
	
分组后筛选	group by后的结果集      group by后		having

问题1:分组函数作筛选能不能放在where后面
答:不能

问题2:where——group by——having

通常来说,能用分组前筛选的,尽可能使用分组前筛选,提升效率

三、分组能够按单个字段也能够按多个字段
四、能够搭配着排序使用




*/



#引入:查询每一个部门的员工个数

SELECT COUNT(*) FROM employees WHERE department_id=90;
#1.简单的分组

#案例1:查询每一个工种的员工平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

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

SELECT COUNT(*),location_id
FROM departments
GROUP BY location_id;


#二、能够实现分组前的筛选

#案例1:查询邮箱中包含a字符的 每一个部门的最高工资

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


#案例2:查询有奖金的每一个领导手下员工的平均工资

SELECT AVG(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;



#三、分组后筛选

#案例:查询哪一个部门的员工个数>5

#①查询每一个部门的员工个数
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;

#② 筛选刚才①结果

SELECT COUNT(*),department_id
FROM employees

GROUP BY department_id

HAVING COUNT(*)>5;


#案例2:每一个工种有奖金的员工的最高工资>12000的工种编号和最高工资

SELECT job_id,MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;


#案例3:领导编号>102的每一个领导手下的最低工资大于5000的领导编号和最低工资

manager_id>102

SELECT manager_id,MIN(salary)
FROM employees
GROUP BY manager_id
HAVING MIN(salary)>5000;


#4.添加排序

#案例:每一个工种有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序

SELECT job_id,MAX(salary) m
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING m>6000
ORDER BY m ;

#5.按多个字段分组

#案例:查询每一个工种每一个部门的最低工资,并按最低工资降序

SELECT MIN(salary),job_id,department_id
FROM employees
GROUP BY department_id,job_id
ORDER BY MIN(salary) DESC;

3.6 链接查询

含义

当查询中涉及到了多个表的字段,须要使用多表链接
select 字段1,字段2
from 表1,表2,...;

笛卡尔乘积:当查询多个表时,没有添加有效的链接条件,致使多个表全部行实现彻底链接
如何解决:添加有效的链接条件

分类

按年代分类:
  	sql92:至关于只有sql99的内链接部分
  		等值
  		非等值
  		自链接
	也支持一部分外链接(用于oracle、sqlserver,mysql不支持)
	
	sql99【推荐使用】
        内链接
            等值
            非等值
            自链接
        外链接
            左外
            右外
            全外(mysql不支持)
        交叉链接

SQL 92语法

一、等值链接
  语法:
  	select 查询列表
  	from 表1 别名,表2 别名
  	where 表1.key=表2.key
  	【and 筛选条件】
  	【group by 分组字段】
  	【having 分组后的筛选】
  	【order by 排序字段】

  特色:
  	① 通常为表起别名
  	②多表的顺序能够调换
  	③n表链接至少须要n-1个链接条件
  	④等值链接的结果是多表的交集部分


  二、非等值链接
  语法:
  	select 查询列表
  	from 表1 别名,表2 别名
  	where 非等值的链接条件
  	【and 筛选条件】
  	【group by 分组字段】
  	【having 分组后的筛选】
  	【order by 排序字段】
  	
  三、自链接【同一个表拆分红多个表】
  语法:
  	select 查询列表
  	from 表 别名1,表 别名2
  	where 等值的链接条件
  	【and 筛选条件】
  	【group by 分组字段】
  	【having 分组后的筛选】
  	【order by 排序字段】

SQL 99语法

一、内链接
  语法:
  select 查询列表
  from 表1 别名
  【inner】 join 表2 别名 on 链接条件
  where 筛选条件
  group by 分组列表
  having 分组后的筛选
  order by 排序列表
  limit 子句;

  特色:
  ①表的顺序能够调换
  ②内链接的结果=多表的交集
  ③n表链接至少须要n-1个链接条件

  分类:
  等值链接
  非等值链接
  自链接

  二、外链接
  语法:
  select 查询列表
  from 表1 别名
  left|right|full【outer】 join 表2 别名 on 链接条件
  where 筛选条件
  group by 分组列表
  having 分组后的筛选
  order by 排序列表
  limit 子句;
  特色:
  ①查询的结果=主表中全部的行,若是从表和它匹配的将显示匹配行,若是从表没有匹配的则显示null
  ②left join 左边的就是主表,right join 右边的就是主表
    full join 两边都是主表
  ③通常用于查询除了交集部分的剩余的不匹配的行

  三、交叉链接

  语法:
  select 查询列表
  from 表1 别名
  cross join 表2 别名;

  特色:
  相似于笛卡尔乘积

sql92语法链接查询示例:(不推荐)

#进阶6:链接查询
/*
含义:又称多表查询,当查询的字段来自于多个表时,就会用到链接查询

笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行

发生缘由:没有有效的链接条件
如何避免:添加有效的链接条件

分类:

	按年代分类:
	sql92标准:仅仅支持内链接
	sql99标准【推荐】:支持内链接+外链接(左外和右外)+交叉链接
	
	按功能分类:
		内链接:
			等值链接
			非等值链接
			自链接
		外链接:
			左外链接
			右外链接
			全外链接
		
		交叉链接


*/

SELECT * FROM beauty;

SELECT * FROM boys;


SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

#1、sql92标准
#一、等值链接
/*

① 多表等值链接的结果为多表的交集部分
②n表链接,至少须要n-1个链接条件
③ 多表的顺序没有要求
④通常须要为表起别名
⑤能够搭配前面介绍的全部子句使用,好比排序、分组、筛选


*/



#案例1:查询女神名和对应的男神名
SELECT NAME,boyName 
FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

#案例2:查询员工名和对应的部门名

SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id`=departments.`department_id`;



#二、为表起别名
/*
①提升语句的简洁度
②区分多个重名的字段

注意:若是为表起了别名,则查询的字段就不能使用原来的表名去限定

*/
#查询员工名、工种号、工种名

SELECT e.last_name,e.job_id,j.job_title
FROM employees  e,jobs j
WHERE e.`job_id`=j.`job_id`;


#三、两个表的顺序是否能够调换

#查询员工名、工种号、工种名

SELECT e.last_name,e.job_id,j.job_title
FROM jobs j,employees e
WHERE e.`job_id`=j.`job_id`;


#四、能够加筛选


#案例:查询有奖金的员工名、部门名

SELECT last_name,department_name,commission_pct

FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;

#案例2:查询城市名中第二个字符为o的部门名和城市名

SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id` = l.`location_id`
AND city LIKE '_o%';

#五、能够加分组


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

SELECT COUNT(*) 个数,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;


#案例2:查询有奖金的每一个部门的部门名和部门的领导编号和该部门的最低工资
SELECT department_name,d.`manager_id`,MIN(salary)
FROM departments d,employees e
WHERE d.`department_id`=e.`department_id`
AND commission_pct IS NOT NULL
GROUP BY department_name,d.`manager_id`;
#六、能够加排序


#案例:查询每一个工种的工种名和员工的个数,而且按员工个数降序

SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;




#七、能够实现三表链接?

#案例:查询员工名、部门名和所在的城市

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`
AND city LIKE 's%'

ORDER BY department_name DESC;



#二、非等值链接


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


SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`
AND g.`grade_level`='A';

/*
select salary,employee_id from employees;
select * from 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);

*/


#三、自链接

#案例:查询 员工名和上级的名称

SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`;

sql99语法链接查询示例:(推荐)

#2、sql99语法
/*
语法:
	select 查询列表
	from 表1 别名 【链接类型】
	join 表2 别名 
	on 链接条件
	【where 筛选条件】
	【group by 分组】
	【having 筛选条件】
	【order by 排序列表】
	

分类:
内链接(★):inner
外链接
	左外(★):left 【outer】
	右外(★):right 【outer】
	全外:full【outer】
交叉链接:cross 

*/


#一)内链接
/*
语法:

select 查询列表
from 表1 别名
inner join 表2 别名
on 链接条件;

分类:
等值
非等值
自链接

特色:
①添加排序、分组、筛选
②inner能够省略
③ 筛选条件放在where后面,链接条件放在on后面,提升分离性,便于阅读
④inner join链接和sql92语法中的等值链接效果是同样的,都是查询多表的交集



*/


#一、等值链接
#案例1.查询员工名、部门名

SELECT last_name,department_name
FROM departments d
 JOIN  employees e
ON e.`department_id` = d.`department_id`;



#案例2.查询名字中包含e的员工名和工种名(添加筛选)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=  j.`job_id`
WHERE e.`last_name` LIKE '%e%';



#3. 查询部门个数>3的城市名和部门个数,(添加分组+筛选)

#①查询每一个城市的部门个数
#②在①结果上筛选知足条件的
SELECT city,COUNT(*) 部门个数
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING COUNT(*)>3;




#案例4.查询哪一个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)

#①查询每一个部门的员工个数
SELECT COUNT(*),department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY department_name

#② 在①结果上筛选员工个数>3的记录,并排序

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

#5.查询员工名、部门名、工种名,并按部门名降序(添加三表链接)

SELECT last_name,department_name,job_title
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 department_name DESC;

#二)非等值链接

#查询员工的工资级别

SELECT salary,grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;
 
 
 #查询工资级别的个数>20的个数,而且按工资级别降序
 SELECT COUNT(*),grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
 GROUP BY grade_level
 HAVING COUNT(*)>20
 ORDER BY grade_level DESC;
 
 
 #三)自链接
 
 #查询员工的名字、上级的名字
 SELECT e.last_name,m.last_name
 FROM employees e
 JOIN employees m
 ON e.`manager_id`= m.`employee_id`;
 
  #查询姓名中包含字符k的员工的名字、上级的名字
 SELECT e.last_name,m.last_name
 FROM employees e
 JOIN employees m
 ON e.`manager_id`= m.`employee_id`
 WHERE e.`last_name` LIKE '%k%';
 
 
 #2、外链接
 
 /*
 应用场景:用于查询一个表中有,另外一个表没有的记录
 
 特色:
 一、外链接的查询结果为主表中的全部记录
	若是从表中有和它匹配的,则显示匹配的值
	若是从表中没有和它匹配的,则显示null
	外链接查询结果=内链接结果+主表中有而从表没有的记录
 二、左外链接,left join左边的是主表
    右外链接,right join右边的是主表
 三、左外和右外交换两个表的顺序,能够实现一样的效果 
 四、全外链接=内链接的结果+表1中有但表2没有的+表2中有但表1没有的
 */
 
 #引入:查询男友 不在男神表的的女神名
 
 SELECT * FROM beauty;
 SELECT * FROM boys;
 
 #左外链接
 SELECT b.*,bo.*
 FROM boys bo
 LEFT OUTER JOIN beauty b
 ON b.`boyfriend_id` = bo.`id`
 WHERE b.`id` IS NULL;
 
 
 #案例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;
 
 
 #右外
 
 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;
 
 
 #全外
  
 USE girls;
 SELECT b.*,bo.*
 FROM beauty b
 FULL OUTER JOIN boys bo
 ON b.`boyfriend_id` = bo.id;
 

 #交叉链接
 
 SELECT b.*,bo.*
 FROM beauty b
 CROSS JOIN boys bo;
 
 
 
 #sql92和 sql99pk
 /*
 功能:sql99支持的较多
 可读性:sql99实现链接条件和筛选条件的分离,可读性较高
 */

3.7 子查询

含义

嵌套在其余语句内部的select语句称为子查询或内查询,
外面的语句能够是insert、update、delete、select等,通常select做为外面语句较多
外面若是为select语句,则此语句称为外查询或主查询

分类

一、按出现位置
select后面:
		仅仅支持标量子查询
from后面:
		表子查询
where或having后面:
		标量子查询
		列子查询
		行子查询
exists后面:
		标量子查询
		列子查询
		行子查询
		表子查询

二、按结果集的行列
标量子查询(单行子查询):结果集为一行一列
列子查询(多行子查询):结果集为多行一列
行子查询:结果集为多行多列
表子查询:结果集为多行多列

示例

where或having后面
  一、标量子查询
  案例:查询最低工资的员工姓名和工资
  ①最低工资
  select min(salary) from employees

  ②查询员工的姓名和工资,要求工资=①
  select last_name,salary
  from employees
  where salary=(
  	select min(salary) from employees
  );

  二、列子查询
  案例:查询全部是领导的员工姓名
  ①查询全部员工的 manager_id
  select manager_id
  from employees

  ②查询姓名,employee_id属于①列表的一个
  select last_name
  from employees
  where employee_id in(
  	select manager_id
  	from employees
  );

3.8 分页查询

应用场景

当要查询的条目数太多,一页显示不全

语法

select 查询列表
from 表
limit 【offset,】size;
注意:
offset表明的是起始的条目索引,默认从0卡死
size表明的是显示的条目数

公式:
假如要显示的页数为page,每一页条目数为size
select 查询列表
from 表
limit (page-1)*size,size;

3.9 联合查询

含义

union:合并、联合,将屡次查询结果合并成一个结果
2、语法
查询语句1
union 【all】
查询语句2
union 【all】
...

意义

将一条比较复杂的查询语句拆分红多条语句
适用于查询多个表的时候,查询的列基本是一致

特色

要求多条查询语句的查询列数必须一致
要求多条查询语句的查询的各列类型、顺序最好一致
union 去重,union all包含重复项

3.10 查询总结

语法:

​ select 查询列表 ⑦ ​ from 表1 别名 ① ​ 链接类型 join 表2 ② ​ on 链接条件 ③ ​ where 筛选 ④ ​ group by 分组列表 ⑤ ​ having 筛选 ⑥ ​ order by排序列表 ⑧ ​ limit 起始条目索引,条目数; ⑨

相关文章
相关标签/搜索