实现数据持久化;
可储存大量数据;
方便检索;
保证数据的一致性、完整性;
安全,可共享;
通过组合分析,获取新数据
commands end with ; or \g
show database;
use 库名;
show tables;
show tables from 库名;
查询test数据库里面的表
当前的数据库还是在mysql,因为没有用use test
show columns from 表名;
select database();
create table stuinfo(
stuid int,
tsunami varchar(20),
gender char,
borndate datetime);
int代表数值数据类型
varchar代表字符串数据类型
char代表代表单个字符
datetime代表日期和时间数据类型,最后一行数据不用逗号分隔
一般不存储年龄而是存储生日,年龄会变生日不会变
desc stuinfo;
select * from stuinfo;
insert into stuinfo values(1,'张无忌','男','1998-3-3');
update stuinfo set borndate='1980-1-1' where stuid=1;
delete from stuinfo where stuid=1;
alter table stuinfo add column email varchar(20);
drop table stuinfo;
select 查询列表 from 表名;
不涉及到表中的字段可以不写来自于某个表
select 100;
select 100%3;
select last_name from employees;
如果表名是关键字,需要加着重号``
select last_name,email,employee_id from employees;
select * from employees;
select database(); 查询当前所在的数据库
select version(); 查询当前数据库服务器的版本
select user();
方式一:使用AS关键字
select user() as 用户名;
select user() as “用户名”;
select user() as ‘用户名’;
以上三种形式都️,什么时候需要加引号,例如:
select last_name as 姓 名
from employees; ❌
姓名之间有空格,系统无法识别
select last_name as "姓 名" from empolyees;☑️
方式二:使用空格
select user() 空格 用户名;
select user() 空格 “用户名”;
select user() 空格 ‘用户名’;
select last_name 空格 “姓 名” from employees;
需求:查询first_name和last_name拼接成的全名,最终起别名为:姓 名。
JAVA中 + 的作用:
SELECT CONCAT(first_name,last_name) AS "姓 名"
FROM employees;
需求:查询员工涉及到的部门编号有哪些
select distinct departement_id from employees;
desc employees;
show columns from employees;
显示出表employees的全部列,各列之间用逗号连接,列名显示成OUT_PUT
错误答案❌
SELECT CONCAT (employee_id,’,’,first_name,’,’,last_name,’,’,salary,’,’,commission_pct) AS “OUT_PUT”
FROM employees;
结果有很多NULL值
原因:commission_pct包含NULL值
拼接的时候要注意,如果其中有一个参数为NULL,那结果也为NULL。所以拼接时,NULL值不能直接用于拼接。
我们希望如果它为NULL时,不拼接它,当做一个空字符;不为NULL时,该是啥就拼接啥。这里需要借助一个函数IFNULL函数。
- 表达式1:可能为NULL的字段或表达式
- 表达式2:如果表达式1为NULL,则最终结果显示的值
- 功能:如果表达式1为NULL,则显示表达式2;否则显示表达式1
SELECT commission_pct,IFNULL(commission_pct,‘空’)
FROM employees;
select concat(employee_id,',',first_name,',',last_name,',',salary,',',IFNULL(commission_pct,'') AS "OUT_PUT"
FROM employees;
select version();
select database();
select user();
select ifnull(字段名,表达式)
select concat(字符1,字符2,字符3);拼接函数
select length(字符/字段);获取字节长度
select 查询列表
from 表名
where 筛选条件;
1⃣️from子句
2⃣️where子句
3⃣️select子句
SELECT *
FROM employees
WHERE department_id <> 100;
SELECT last_name,department_id,email
FROM employees
WHERE department_id<50 OR department_id>100;
SELECT last_name,department_id,email
FROM employees
WHERE NOT (department_id>=50 AND department_id<=100);
SELECT *
FROM employees
WHERE commission_pct>0.03 OR (employee_id>=60 AND employee_id<=110);
NOT LIKE
功能:一般和通配符搭配使用,对字符型数据进行部分匹配查询
常见的通配符:
_ 代表任意单个字符
% 代表任意多个字符,支持0-多个
案例1:查询姓名中包含字符a的员工信息
注意⚠️:字符数据要用单引号
注意⚠️:包含 a 代表前后可能都有其他字符
SELECT *
FROM employees
WHERE last_name LIKE '%a%';
SELECT *
FROM employees
WHERE last_name LIKE '%e';
SELECT *
FROM employees
WHERE last_name LIKE '__x%';
SELECT *
FROM employees
WHERE last_name LIKE '_$_%' ESCAPE '$';
转义字符可以自行设定,ESCAFE ' ′ 代 表 设 定 '代表设定 ′代表设定为转义字符
功能:判断某字段的值是否在指定的列表
a IN(常量值1,常量值2,常量值3,…)
a NOT IN(常量值1,常量值2,常量值3,…)
案例1:查询部门编号是30/50/90的员工名、部门编号
方式一:
SELECT last_name,department_id
FROM employees
WHERE department_id IN(30,50,90);
方式二:逻辑表达式
SELECT last_name,department_id
FROM employees
WHERE department_id=30,
OR department_id=50,
OR department_id=90;
SELECT *
FROM employees
WHERE job_id NOT IN('SH_CLERK','IT_PROG');
方式2:
SELECT *
FROM employees
WHERE NOT(job_id='SH_CLERK'
OR job_id='IT_PROG');
SELECT department_id,last_name
FROM employees
WHERE department_id BETWEEN 30 AND 90;
方式2:
SELECT department_id,last_name
FROM employees
WHERE department_id>=30 AND department_id<=90;
注意⚠️:between and包含两个临界值;且顺序不能颠倒
SELECT last_name,salary,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
WHERE salary*12*(1+IFNULL(commission_pct,0)) NOT BETWEEN 100000 AND 200000;
SELECT *
FROM employees
WHERE commission_pct IS NULL;
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;
= 只能判断普通内容
IS 只能判断NULL值
<=>安全等于,既能判断普通内容,又能判断NULL值,阅读性差
SELECT last_name
FROM employees
WHERE last_name LIKE '%a%' AND last_name LIKE '%e%';
SELECT last_name
FROM employees
WHERE last_name LIKE '%a%e%' OR last_name LIKE '%e%a%';
SELECT 查询列表
FROM 表名
【WHERE 筛选条件】可省略
ORDER BY 排序列表(可以多个)
案例1: 将员工编号>120的员工信息进行工资的升序
SELECT *
FROM employees
WHERE employee_id>120
ORDER BY salary ASC;
案例2: 将员工编号>120的员工信息进行工资的降序
SELECT *
FROM employees
WHERE employee_id>120
ORDER BY salary DESC;
SELECT *,salary*12*(1+IFFULL(commission_pct,0)) 年薪
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary*12*(1+IFFULL(commission_pct,0)) DESC;
SELECT *,salary*12*(1+commission_pct) 年薪
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY 年薪 DESC;
注意⚠️:WHERE条件筛选为什么不能用别名?
因为执行顺序是FROM,WHERE,SELECT,别名是在SELECT子句中起的,在执行WHERE子句时还不知道别名。
SELECT last_name
FROM employees
ORDER BY LENGTH(last_name);
SELECT last_name,salary,department_id
FROM employees
ORDER BY salary ASC,department_id DESC;
-案例:按第二列排序(first_name)
SELECT * FROM employees
ORDER BY 2 DESC;
语意性较差
SELECT * FROM employees
ORDER BY first_name DESC;
SELECT *
FROM employees
WHERE email LIKE '%e%'
ORDER BY LENGTH(email) DESC,department_id ASC;
SELECT CONCAT('hello,',first_name,last_name) 备注
FROM employees;
SELECT LENGTH('hello,郭襄');
结果不是8,而是12,一个汉字识别成3个字节
一个汉字或者一个字母都是一个字符
SELECT CHAR_LENGTH('hello,郭襄');
结果是8
substr(str,pos):截取从pos开始的所有字符
substr(str,pos,len):截取len个从pos开始的字符
可以缩写为SUBSTR
susbtr(str完整的字符串,起始索引,截取的字符长度/个数)
**susbtr(str,起始索引)不写截取字符长度,默认把后面都截取出来
注意⚠️:起始索引从1开始
SELECT SUBSTR('张三丰爱上了郭襄',1,3);
SELECT SUBSTR('张三丰爱上了郭襄',7,2);
或写成
SELECT SUBSTR('张三丰爱上了郭襄',7);
SELECT INSTR('三打白骨精aaa白骨精bb白骨精','白骨精');
结果为3
SELECT TRIM(' 虚 竹 ') AS a;
结果为虚 竹
SELECT TRIM('x' FROM 'xxxxxx虚xxx竹xxxxxxxxxx') AS a;
结果为虚xxx竹
SELECT LPAD('木婉清',10,'a');
SELECT UPPER(SUBSTR(first_name,1,1)) FROM employees;
SELECT LOWER(SUBSTR(first_name,2)) FROM employees;
SELECT UPPER(last_name) FROM employees;
SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),LOWER(SUBSTR(first_name,2)),'_',UPPER(last_name)) "OUTPUT"
FROM employees;
SELECT STRCMP('abc','aac');
按字典顺序,第一个字符a相等,比较第二个字符b>a,所以结果返回1
SELECT LEFT('鸠摩智',1);
结果为 鸠
SELECT RIGHT('鸠摩智',1);
结果为 智
SELECT RIGHT('鸠摩智',2);
结果为 摩智
SELECT ABS(-2.4);
结果返回2.4
SELECT CEIL(1.09);
结果返回2
SELECT CEIL(0.09);
结果返回1
SELECT CEIL(-1.09);
结果返回-1
SELECT FLOOR(1.09);
结果返回1
SELECT FLOOR(0.09);
结果返回0
SELECT FLOOR(-1.09);
结果返回-2
SELECT ROUND(1.8712345);
结果返回2
SELECT ROUND(1.8712345,2);
结果返回1.87
SELECT TURNCATE(1.8712345,0);
结果返回1
SELECT TURNCATE(1.8712345,1);
结果返回1.8
SELECT MOD(-10,3);
SELECT -10%3
两者结果返回一样
a%b=a-a/bb, 绝对值取余,符号和a一致
-10%3=-10-(-10)/33=-1
SELECT NOW();
SELECT CURDATE();
SELECT CURTIME();
SELECT DATEDIFF('1998-7-16','2019-7-13');
结果为-7667,前面减后面
SELECT DATE_FORMAT('1998-7-16','%Y年%m月%d日 %H小时%i分钟%s秒') 出生日期;
SELECT DATE_FORMAT(hiredate,'%Y年%m月%d日 %H小时%i分钟%s秒') 入职日期
FROM employees;
SELECT * FROM employees
WHERE hiredate<STR_TO_DATE('3/15 1998','%m/%d %Y');
date(str)将日期格式转化为年月日
year(date)
month(date)
day(date)
hour(date)
minute(date)
second(date)
SELECT IF(100>9,'好','坏');
结果返回 好
SELECT IF(commission_pct IS NULL,0,salary*12*commission_pct) 奖金
FROM employees;
情况1:类似于switch语句,可以实现等值判断
CASE (表达式)
WHEN 值1 THEN 结果1
WHEN 值2 THEN 结果2
…
ELSE 结果n (ESLE可省略)
END
案例:部门编号是30,工资显示为2倍;
部门编号是50,工资显示为3倍;
部门编号是60,工资显示为4倍;
否则不变
显示部门编号,新工资,旧工资
SELECT department_id,salary,
CASE department_id
WHEN 30 THEN salary*2
WHEN 50 THEN salary*3
WHEN 60 THEN salary*4
ELSE salary
END newsalary
FROM employees;
情况2:类似于多重IF语句,实现区间判断
CASE
WHEN 条件1 THEN 结果1
WHEN 条件2 THEN 结果2
…
ELSE 结果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 grade
FROM employees;
SELECT NOW();
SELECT employee_id,last_name,salary,salary*1.2 "new salary"
FROM employees;
SELECT LENGTH(last_name) 长度
FROM employees
ORDER BY SUBSTR(last_name,1,1) ASC;
SELECT CONCAT(last_name,'earns',salary,'monthly but wants',salary*3) "Dream Salary"
FROM employees;
SELECT last_name,job_id,
CASE job_id
WHEN 'AD_PRES' THEN 'A'
WHEN 'ST_MAN' THEN 'B'
WHEN 'IT_PROG' THEN 'C'
WHEN 'SA_REP' THEN 'D'
WHEN 'ST CLERK' THEN 'E'
END Grade
FROM employees;
注意⚠️:除了数值型,其他都要用引号
没有ELSE,可以不用写
分组函数往往用于实现将一组数据进行统计计算,最终得到一个值,又称为聚合函数或统计函数
SUM(字段名):求和
AVG(字段名):求平均数
MAX(字段名):求最大值
MIN(字段名):求最小值
COUNT(字段名):计算非空字段值的个数
SELECT SUM(salary),AVG(salary),MIN(salary),MAX(salary),COUNT(salary)
FROM employees;
SELECT COUNT(employee_id) FROM employees;
查询员工表中有佣金的人数;
SELECT COUNT(salary) FROM employees;
查询员工表中月薪大于2500的人数;
SELECT COUNT(salary)
FROM employees
WHERE salary>2500;
查询有领导的人数;
SELECT COUNT(manager_id) FROM employees;
COUNT补充:
SELECT COUNT(*)FROM employees;
SELECT COUNT(*)FROM employees WHERE department_id=30;
SELECT COUNT(1)FROM employees;
SELECT COUNT(1)FROM employees WHERE department_id=30;
返回结果和前面一样,相当于增加一列常量列,值都为1,最后计算有多少个1
SELECT COUNT(DISTINCT department_id) FROM employees;
SELECT SUM(salary),department_id
FROM employees
GROUP BY department_id;
当需要分组查询时需要使用GROUP BY子句
SELECT 查询列表(一般为分组函数,被分组的字段)
FROM 表名
WHERE 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选
ORDER BY 排序列表;
筛选的基表 | 使用的关键词 | 位置 | |
---|---|---|---|
分组前筛选 | 原始表FROM后的表 | WHERE | GROUP BY 前 |
分组后筛选 | 分组后的结果集 | HAVING | GROUP BY后 |
WHERE—GROUP BY—HAVING
分组函数做条件只可能放在HAVING后面
案例1:查询每个工种(被分组字段)的员工平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
案例2:每个领导的手下人数
SELECT COUNT(*),manager_id
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_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;
案例1:查询哪个部门的员工个数>5
SELECT COUNT(*) 员工个数,departmenet_id
FROM employees
GROUP BY department_id;
SELECT COUNT(*) 员工个数,departmenet_id
FROM employees
WHERE COUNT(*)>5
GROUP BY department_id;
系统报错,因为执行顺序是FROM子句,WHERE子句,SELECT子句,WHERE子句无法从FROM employees中筛选出COUNT(*)列,应该在GROUP BY分组之后可以筛选。WHERE不支持后面加分组函数做条件。
SELECT COUNT(*) 员工个数,departmenet_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>5;
HAVING支持后面加分组函数做条件,支持分组后做筛选
案例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的领导编号和最低工资
SELECT manager_id,MIN(salary) 最低工资
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000;
SELECT MAX(salary) 最高工资,job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id;
分析2:从前面的结果中筛选最高工资>6000
SELECT MAX(salary) 最高工资,job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>6000;
分析3: 按最高工资升序排序
SELECT job_id,MAX(salary) 最高工资
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>6000
ORDER BY 最高工资 ASC;
SELECT MIN(salary) 最低工资,job_id,department_id
FROM employees
GROUP BY job_id,department_id
ORDER BY MIN(salary) DESC;
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积:表1有m行,表2有n行,结果=m*n行
发生原因:没有有效的连接条件
解决办法:添加有效的连接条件
SELECT 查询列表(的 后面是什么就写什么)
FROM 表名1 别名1,表名2 别名2,…
WHERE 等值连接的连接条件
案例:查询员工名和部门名
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.deparmtent_id=d.department_id;
当表起了别名后,不能再用原表明限定字段,应该用别名来限定
employees.last_name ❌
e.last_name ☑️
案例1:查询部门编号>100的部门名和所在的城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.location_id=l.location_id
AND d.department_id>100;
案例2:查询有奖金的员工名、部门名
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.department_id=d.department_id
AND e.commission_pct IS NOT NULL;
案例3:查询城市名中第二个字符为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 locations l,departments d
WHERE l.location_id=d.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 e.commission_pct IS NOT NULL
GROUP BY department_name,d.manager_id;
案例1:查询部门中员工个数>10的部门名,并按部门名降序
SELECT COUNT(*) 员工个数,department_name
FROM employees e,departments d
WHERE e.department_id=d.department_id
GROUP BY department_name
HAVING COUNT(*)>10
ORDER BY department_name DESC;
案例2:查询每个工种的员工个数和工种名,并按员工个数降序
SELECT COUNT(*) 员工个数,job_title
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_if=d.department_id
AND d.location_id=l.location_id;
案例1: 查询员工的工资和工资级别
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.lowest_sal AND g. highest_sal;
案例:查询员工编号、员工名以及上级的名称
SELECT e.employee_id,e.last_name,m.manager_id,m.last_name
FROM employees e,employees m
WHERE e.manager_id=m.employee_id;
语法:
SELECT 查询列表
FROM 表名1 列名
INNER JOIN 表名2 别名 ON 连接条件 (INNER可省略)
INNER JOIN 表名3 别名 ON 连接条件
WHERE 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选
ORDER BY 排序列表;
SQL92和SQL99的区别:
SQL99使用JOIN关键字代替SQL92中的逗号连接各表,并且将连接条件ON和筛选条件WHERE进行了分离,阅读性更强
案例:查询员工名和部门名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.department_id=d.e.department_id;
案例:查询部门编号>100的部门名和所在的城市名
SELECT department_name,city
FROM departments d
INNER JOIN locations l
ON d.location_id=l.location_id
WHERE d.department_id>100;
案例:查询每个城市的部门个数
SELECT COUNT(*) 部门个数,l.city
FROM departments d
INNER JOIN locations l
ON d.location_id=l.location_id
GROUP BY l.city;
select子句用city取代l.city可以吗???
案例:查询部门员工个数>10的部门名,并按员工个数降序
SELECT COUNT(*) 员工个数,d.department_name
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id
GROUP BY d.department_id
HAVING 员工个数>10
ORDER BY 员工个数 DESC;
HAVING支持别名
案例:查询部门编号在10-90之间的每个工资级别的员工个数
SELECT COUNT(*) 员工个数,grade
FROM employees e
INNER JOIN sal_grade g
ON e.salary BETWEEN g.min_salary AND g.max_salary
WHERE e.department_id BETWEEN 10 AND 90
GROUP BY g.grade;
案例:查询员工名和对应的领导名
SELECT e.last_name,m.last_name
FROM employees e
INNER JOIN employees m
ON e.manager_id=m.manager_id;
案例:将当前日期显示成xxxx年xx月xx日
SELECT date_format(now(),'%Y年%m月%d日');
案例:
已知学员信息表stuinfo: stuId, stuName, gender, majorId
已知专业表major: id, majorName
已知成绩表result: id, majorId, stuId, score
SELECT s.stuname,m.majorname,r.score
FROM stuinfo s,major m,result r
WHERE s.majorid=m.id AND r.stuid=s.stuid
AND s.gender='男';
SELECT s.stuName,m.majorName,r.score
FROM stuinfo s
INNER JOIN major m ON s.majorid=m.id
INNER JOIN result r ON s.stuid=r.stuid
WHERE s.gender='男';
SELECT AVG(score) 平均成绩,s.majorid,s.gender
FROM stuinfo s
INNER JOIN result r
ON s.majorid=r.majorid
GROUP BY s.gender,s.majorid (用r.majorid也可)
ORDER BY 平均成绩 DESC;
查询结果为主表中的所有记录,如果从表有匹配项,则显示匹配项;如果从表没有匹配项,则显示为NULL值
应用场景:一般用于查询主表中有但从表没有的记录
SELECT 查询列表
FROM 表1 别名
LEFT/RIGHT/FULL OUTER JOIN 表2 别名 (OUTER可省略)
ON 连接条件
WHERE 筛选条件
GROUP BY
HAVING
ORDER
LIMIT;
SELECT d.department_id,d.department_name
FROM departments d
LEFT JOIN employees e ON d.department_id=e.department_id
WHERE e.employee_id IS NULL;
筛选条件用从表主键列,因为主键列没有NULL值,如果为NULL值,一定是因为没有匹配的原因。如果用其他列,可能存在某些本身就为NULL值。
SELECT l.city
FROM departments d
RIGHT JOIN loctations l ON l.location_id=d.location_id
WHERE d.department_id IS NULL;
SELECT d.*,e.*
FROM departments d
LEFT JOIN employees e ON d.department_id=e.department_id
WHERE d.department_name='SAL' OR d.department_name='IT';
当一个查询语句中又嵌套了另一个完整的SELECT语句,则被嵌套的select语句,称为子查询或内查询,外面的select语句称为主查询或外查询
子查询不一定必须出现在select语句内部,只是出现在select语句内部的时候较多
按子查询出现的位置进行分类:
第一步:查询Zlotkey的部门编号
SELECT department_id
FROM employees
WHERE last_name='Zlotkey';
第二步:查询department_id=1.题的员工姓名和工资
SELECT last_name,salary
FROM employees
WHERE department_id=(
SELECT department_id
FROM employees
WHERE last_name='Zlotkey');
第一步:查询平均工资
SELECT AVG(salary)
FROM employees;
第二步:查询salary>第一步结果的信息
SELECT employee_id,last_name,salary
FROM employees
WHERE salary>(SELECT AVG(salary) FROM employees);
第一步:查询50号部门的最低工资
SELECT MIN(salary)
FROM employees
WHERE department_id=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⃣️查询最高工资
SELECT MAX(salary)
FROM employees;
2⃣️查询结果1⃣️的员工
SELECT CONCAT(first_name,last_name) "姓.名"
FROM employees
WHERE salary=(
SELECT MAX(salary)
FROM employees
);
in:判断某字段是否在指定列表内
any/some:判断某字段的值是否满足其中任意一个
x>any(10,30,50)等价于x>min(10)
x=any(10,30,50)等价于x in(10,30,50)
all:判断某字段的值是否满足里面所有的
x>all(10,30,50)等价于x>max(10,30,50)
all和any语意性较差,一般都可以被代替
案例:返回location_id是1400或1700的部门中的所有员工姓名
第一步:查询location_id是1400或1700的部门
SELECT department_id
FROM departments
WHERE location_id IN(1400,1700);
结果是多行单列
第二步:查询department_id=第一步的姓名
SELECT last_name
FROM employees
WHERE department_id IN(
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN(1400,1700)
);
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG';
第二步:查询其他部门工资<任意一个第一步的结果
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ANY(
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
);
等价于
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
SELECT MAX(salary)
FROM employees
WHERE job_id='IT_PROG'
);
第一步:查询job_id为‘IT_PROG’部门的工资
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG';
第二步:查询其他部门工资<所有第一步的结果
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ALL(
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
);
等价于
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
SELECT MIN(salary)
FROM employees
WHERE job_id='IT_PROG'
);
SELECT
(
SELECT COUNT(*)
FROM employees
WHERE department_id=50
) 个数;
1⃣️查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id;
2⃣️将1⃣️和sal_grade两表连接查询
SELECT dep_ag.department_id,ep_ag.ag,g.grade
FROM sal_grade g
JOIN(
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id
) dep_ag ON dep_ag.ag BETWEEN g.min_salary AND g.max_salary;
SELECT *
FROM employees
WHERE last_name='张三丰';
没有显示结果,表示没有名字叫张三丰的员工信息
SELECT EXISTS(
SELECT *
FROM employees
WHERE last_name='张三丰'
) 有无张三丰;
结果显示为0,0代表没有(FALSE),1代表有(TRUE)
1⃣️查询各部门平均工资
SELECT department_id,AVG(salary) ag
FROM employees
GROUP BY department_id;
2⃣️将1⃣️结果和employees表连接查询
SELECT employee_id,last_name,salary
FROM employees e
JOIN(
SELECT department_id,AVG(salary) ag
FROM employees
GROUP BY department_id
) dep_ag ON e.department_id=dep_ag.department_id
WHERE e.salary>dep_ag.ag;
1⃣️查询姓名中包含字母u的员工所在部门
SELECT DISTINCT department_id
FROM employees
WHERE last_name LIKE '%u%';
2⃣️查询结果1⃣️部门中的员工的员工号和姓名
SELECT employee_id,last_name
FROM employees
WHERE department_id IN(
SELECT department_id
FROM employees
WHERE last_name LIKE '%u%'
);
1⃣️查询管理者是King的员工编号
SELECT employee_id
FROM employees
WHERE last_name='King';
2⃣️查询管理者编号为1⃣️的员工的姓名和工资
SELECT last_name,salary
FROM employees
WHERE manager_id IN(
SELECT employee_id
FROM employees
WHERE last_name='King'
);
1⃣️查询各部门的平均工资中最低的
SELECT department_id,AVG(salary) ag
FROM employees
GROUP BY department_id
ORDER BY ag ASC
LIMIT 1;
2⃣️连接结果1⃣️和departments表
SELECT d.*,dep_ag.ag
FROM departments d
JOIN (
SELECT department_id,AVG(salary) ag
FROM employees
GROUP BY department_id
ORDER BY ag ASC
LIMIT 1
) dep_ag ON d.department_id=dep_ag.department_id;
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MAX(salary) ASC
LIMIT 1;
2⃣️查询部门便是是1⃣️的部门的最低工资
SELECT MIN(salary),department_id
FROM employees
WHERE department_id=(
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MAX(salary) ASC
LIMIT 1
);
应用场景:当页面上的数据一页显示不全,则需要分页显示
分页查询的sql命令请求数据库服务器—>服务器响应查询到的多条数据—>前台页面
SELECT 查询列表
FROM 表1 别名
JOIN 表2 别名
ON 连接条件
WHERE 筛选条件
GROUP BY 分组
HAVING 分组后筛选
ORDER BY 排序列表
LIMIT 起始索引,显示的条目数
执行顺序:
SELECT * FROM emploees LIMIT 0,5;
完全等价于
SELECT * FROM emploees LIMIT 5;
SELECT * FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10,10;
SELECT *
FROM employees
LIMIT (page-1)*size,size;
page size=10
1 LIMIT 0,10
2 LIMIT 10,10
3 LIMIT 20,10
4 LIMIT 30,10
说明:当查询结果来自于多张表,但多张表之间没有关联,这个时候往往使用联合查询,也称UNION查询
完整的SELECT语句1 UNION
完整的SELECT语句2 UNION
完整的SELECT语句3 UNION
…
完整的SELECT语句n
SELECT * FROM chinese WHERE age>20 UNION
SELECT * FROM usa WHERE uage>20;
SELECT uname,uage FROM usa
UNION
SELECT age,'name' FROM chinese;
说明:Data Define Language数据定义语言,用于对数据库和表的管理和操作
CREATE DATABASE 库名;
CREATE DATABASE IF NOT EXISTS 库名;
DROP DATABASE 库名;
DROP DATABASE IF EXISTS stuDB;
意思 | 格式 | n的解释 | 特点 | 效率 | |
---|---|---|---|---|---|
Char | 固定长度字符 | Char(n) | 最大字符个数可以省略不写CHAR,默认:1 | 不管实际存储,开辟的空间都是n个字符 | 高 |
Varchar | 可变长度字符 | Varchar(n) | 最大的字符个数,必选 | 根据实际存储决定开辟的空间 | 低 |
保存范围 | 所占字节 | |
---|---|---|
Datetime | 1900-1-1~xxxx年 能表示的日期范围较大 | 8 |
Timestamp | 1970-1-1~2038-12-31 能表示的日期范围较小 | 4 |
说明:用于限制表中字段的数据,从而进一步保证数据表的数据是一致的、准确的、可靠的
CREATE TABLE stuinfo(
id INT PRIMARY KEY,
name VARCHAR(20) UNIQUE,
gender CHAR default '男',
age INT CHECK(age>=1 AND age<=100),
email VARCHAR(20) NOT NULL,
majorid INT,
CONSTRAINT fk FOREIGN KEY(majorid) REFERENCES major(id)
);
CREATE TABLE stuinfo(
id INT,
name VARCHAR(20),
gender CHAR default '男',
age INT CHECK(age>=1 AND age<=100),
email VARCHAR(20) NOT NULL,
majorid INT,
PRIMARY KEY(id),#添加主键
CONSTRAINT 名 UNIQUE(name),#添加唯一建
CONSTRAINT fk FOREIGN KEY(majorid) REFERENCES major(id)
);
CREATE TABLE IF NOT EXISTS 表名(
字段名 字段类型 「字段约束」可省略,
字段名 字段类型 「字段约束」,
字段名 字段类型 「字段约束」,
字段名 字段类型 「字段约束」
);
CREATE TABLE IF NOT EXISTS stuinfo(
stuin INT,
stuname VARCHAR(20),
stugender CHAR,
email VARCHAR(20),
borndate DATETIME
);
CREATE TABLE IF NOT EXISTS stuinfo(
stuin INT PRIMARY KEY, #添加了主键约束
stuname VARCHAR(20) UNIQUE NOT NULL,#添加了唯一和非空约束
stugender CHAR DEFAULT '男',#添加了默认约束
email VARCHAR(20) NOT NULL,#添加了非空约束
age INT CHECK(age BETWEEN 1 AND 100)),#添加了检查约束,但Mysql不支持
majorid INT,#外键约束不能直接在后面加,需要在下一行
CONSTRAINT fk_stuinfo_major FOREIGN KEY (majorid) REFERENCES major(id)#添加外键约束 constraint+(约束名,不写的话提供默认名)+ foreign key + 从表列 + references + 主表列
ALTER TABLE 表名 ADD/MODIFY/CHANGE/DROP COLUMN 字段名 字段类型 字段约束(可省略);
modify改列的类型
change改列名
ALTER TABLE stuinfo RENAME TO students;
ALTER TABLE students ADD COLUMN borndate TIMESTAMP NOT NULL;
ALTER TABLE students CHANGE COLUMN borndate birthday(新字段名) DATETIME NULL;
ALTER TABLE students MODIFY COLUMN birthday TIMESTAMP;
ALTER TABLE students DROP COLUMN birthday;
DROP TABLE IF EXISTS 表名;
CREATE TABLE 新表名 LIKE 旧表;
CREATE TABLE newTable1 SELECT * FROM girls.beauty;
CREATE TABLE emp
SELECT last_name,department_id,salary
FROM myemployees,employees
WHERE 1=2; #1=2表示恒不成立
SELECT *
FROM employees
WHERE department_id=50
ORDER BY salary ASC
LIMIT 5;
第一步:查询城市为Toronto的部门编号
SELECT department_id
FROM departments d
JOIN locations l
ON d.location_id=l.location_id
WHERE city='Toronto';
第二步:查询结果1中工资>10000的员工姓名
SELECT last_name
FROM employees
WHERE salary>10000
AND department_id IN(
SELECT department_id
FROM departments d
JOIN locations l
ON d.location_id=l.location_id
WHERE city='Toronto'
);
CREATE TABLE IF NOT EXISTS qqinfo(
qqid INT PRIMARY KEY,
nickname VARCHAR(20) UNIQUE,
email VARCHAR(20) NOT NULL,
gender CHAR
);
DROP TABLE IF EXISTS qqinfo;
定义顺序(书写顺序)
select distinct 查询列表
from 表名1 别名
join 表名2 别名
on 连接条件
where 筛选条件
group by 分组列表
having 分组后筛选
order by 排序列表
limit 条目数
执行顺序
from 子句
join 子句
on子句
where 子句
group by子句
having 子句
select 子句
order by 子句
limit 子句
INSERT INTO 表名(字段名1,字段名2,...) VALUES(值1,值2,...)
INSERT INTO 表名(字段名1,字段名2,...)
VALUES(值1,值2,...),(值1,值2,...),(值1,值2,...),(值1,值2,...);
INSERT INTO stuinfo(stuid,stuname,stugender,email,age,majorid)
VALUES(1,'吴倩','男','[email protected]',12,1);
方法一:字段名和值都不写
INSERT INTO stuinfo(stuid,stuname,stugender,email,majorid)
VALUES(1,'吴倩','男','[email protected]',1);
方法二:写字段名,值写NULL
INSERT INTO stuinfo(stuid,stuname,stugender,email,age,majorid)
VALUES(1,'吴倩','男','[email protected]',NULL,1);
方法一:字段名和值都不写
INSERT INTO stuinfo(stuid,stuname,email,majorid)
VALUES(1,'吴倩','[email protected]',1);
方法二:写字段名,值写DEFAULT
INSERT INTO stuinfo(stuid,stuname,stugender,email,majorid)
VALUES(1,'吴倩',DEFAULT,'[email protected]',1);
INSERT INTO stuinfo VALUES(1,'林忆莲',DEFAULT,'[email protected]',12,3);
CREATE TABLE 表名(
字段名 字段类型 约束 AUTO_INCREMENT,
);
CREATE TABLE gradeinfo(
gradeid INT PRIMARY KEY AUTO_INCREMENT,#设置gradeid为自增长列
gradename VARCHAR(20)
);
写法一:自增长列对应值可以写NULL
INSERT INTO gradeinfo VALUES(NULL,'1年级'),(NULL,'2年级'),(NULL,'4年级');
写法二:直接不写自增长列和对应值
INSERT INTO gradeinfo(gradename) VALUES('1年级'),('2年级'),('4年级');
UPDATE 表名 SET 字段名1=新值1,字段名2=新值2,......
WHERE 筛选条件;
UPDATE stuinfo SET majorid=3,email='[email protected]'
WHERE age<20;
DELETE FROM 表名
WHERE 筛选条件;
案例1:删除姓李的所有信息
DELETE FROM stuinfo
WHERE stuname LIKE '李%';
TRUNCATE TABLE 表名;
案例2:删除表中所有数据
TRUNCATE TABLE stuinfo;
一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败
INSERT INTO stuinfo VALUES(1,'john','男','[email protected]',12)
如果字段和值不对应,整条语句都无法插入,而不是只有不对应字段和值无法插入
SET autocommit=0;
START TRANSACTION;
将张三的钱-5000
UPDATE stuinfo SET balance=balance-5000 WHERE stuid=1;
将赵四的钱+5000
UPDATE stuinfo SET balance=balance+5000 WHERE stuid=2;
COMMIT;
ROLLBACK;
select * from data.dataanalyst
where city = ‘上海’
and education = ‘本科’
or worker = ‘1-3年’
and优先计算,实际运算逻辑如下
select * from data.dataanalyst
where (city = ‘上海’
and education = ‘本科’)
or worker = ‘1-3年’
遇到复杂逻辑,勤用括号()
在select语句中使用别名,但别名不能立刻在select语句中使用。
locate(substr,str)定位函数,获取substr在str中第一次出现的索引.和Excel里find函数功能一样
locate(‘k’,salary):获取k在salary(10k-15k)中的位置
locate(substr,str,从哪个位置开始查找)也可添加第三个参数
和instr函数功能相同,INSTR(str,substr):获取substr在str中第一次出现的索引
left join应用:排除法统计
新人刚进公司需要搞清楚表与表之间的关系和逻辑
leetcode.com 牛客网 刷题
date(str)将日期格式转化为年月日
date_add(str,interval 1 day/week/month)加上一天
power Bi连接mysql,提前写好SQL查询,占用服务器性能,直接返回结果到PowerBI;如果用原始数据在PowerBI里进行查询,会占用自己电脑的性能