学习笔记系列开头惯例发布一些寻亲消息
链接:https://baobeihuijia.com/bbhj/contents/3/199913.html
数据库
-
三个概念区分
- DB:数据库,存储数据的仓库,有组织的数据容器
- DBMS:数据库管理系统
- SQL:几乎所有的DBMS都支持的语言
-
对数据库的大致了解过程
MySQL详细学习教程(建议收藏)-CSDN博客
聚集索引(聚类索引)与非聚集索引(非聚类索引) - 知乎 (zhihu.com)
主键约束(PRIMARY KEY)和唯一约束(UNIQUE)的区别_主键约束和唯一约束有什么区别-CSDN博客
事务ACID理解-CSDN博客
数据库三级模式:外模式、模式和内模式_数据库模式内模式外模式-CSDN博客
-
基础知识
- mysql的索引从1开始,但是分页查询是从0开始起始索引
- 起别名,as或者空格,需要注意**【由于mysql先执行from,所以起了别名后,其他地方就不能再使用原名】**
- mysql中+只有运算符含义,如果遇到字符串就会将字符转化为数据:转化成功继续计算,转化失败则将字符型转化为0,如果其中一个为null那么拼接结果为null
- 字符串拼接:SELECT CONCAT(first_name,last_name) AS “name” FROM employees; 如果其中一个为null那么拼接结果为null
- DESC departments;
- 字段用着重符,如果是加入的字符串要用单引
- IFNULL(字段,0) 字段为null则改为0,不为null则仍为原数据
- 在GBK中一个字符占2个字节,utf8中一个字符占3个字节
-
1、> < = != >= <=
2、and or not
3、like / between and / in / is null -
like 用通配符% 表示任意多的字符,包括0个,下划线表示一个
-
SELECT *
FROM employees
WHERE first_name LIKE ‘%a%’;SELECT *
FROM employees
WHERE first_name LIKE ‘__e__a%’;SELECT *
FROM employees
WHERE last_name LIKE ‘__%’
-
-
between
-
两边都是闭区间、有前后关系
SELECT *
FROM employees
WHERE employee_id BETWEEN 100 AND 120;
-
-
IN: 表示某字段是否满足in列表中的一项,in中的判断逻辑是:是否能找到直接相等?
- SELECT *
FROM employees
WHERE job_id IN (‘IT_PROG’,‘AS_VD’);
- SELECT *
-
IS NULL:等号不能判断null, <=>安全等于符号
- SELECT *
FROM employees
WHERE commission_pct IS NULL; - SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;
- SELECT *
-
排序查询
-
默认为升序、ASC \ DESC
-
一般放在查询的最后边
-
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) AS money FROM employees ORDER BY money DESC; # 按照多个条件进行排序 SELECT * FROM employees ORDER BY salary DESC, employee_id;
-
-
常见函数
-
单行函数:concat / length / ifnull / UPPER / LOWER (变化大小写) / substr(截取字符串) / instr(返回第一次出现的起始索引),trim是去掉左右空格,lpad
# 返回第一次出现的起始索引 SELECT INSTR('zhuahdhqwdhqwo','hq'); # 可以选择去前或者去后 SELECT TRIM('a' FROM 'aaaazhiyaaaaaaa'); # lpad进行左长度填充,超过固定长度就会截断 SELECT LPAD('yyy',10,'-'); # rpad右填充 SELECT RPAD('yyy',10,'-'); # replace SELECT REPLACE('nihaowoshiczy','czy','dameinv'); # round:四舍五入 SELECT ROUND(4.5); SELECT ROUND(1.657,2); # ceil:向上取整,返回大于等于本身的最小整数 # floor:向下取整,返回小于等于本身的最小整数 # truncate 截断 SELECT TRUNCATE(1.666666,3); #mod取余,结果只看被除数的正负号: mod(a,b) = a-a/b*b #时间转换 STR_TO_DATE SELECT STR_TO_DATE('7-31 2023','%c-%d %Y'); SELECT DATE_FORMAT(NOW(),'%Y %c_%d'); select version(); select database(); # 查询时间之差 SELECT DATEDIFF(NOW(),'2000-7-31');
-
流程控制函数
# if SELECT IF(commission_pct IS NULL,'A','B') FROM employees; # case当作switch使用 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 FROM employees; # case当作if else使用 SELECT salary, CASE WHEN salary >20000 THEN 'A' WHEN salary >15000 THEN 'B' WHEN salary >10000 THEN 'C' ELSE 'D' END FROM employees;
-
分组函数:max / min / avg / sum / count 和分组函数一起查询的字段需要和分组函数结果一致
sum和avg不计算考虑null max和min也忽略考虑null count计算的是非空字段的数量 SELECT COUNT(*) FROM employees; SELECT COUNT(1) FROM employees;
-
-
查询
-
分组查询
SELECT MAX(salary),job_id FROM employees GROUP BY job_id; SELECT COUNT(*), department_id FROM employees GROUP BY department_id HAVING COUNT(*)>2; # 查询每个工种有奖金的最高工资大于12000的工种和最高工资 SELECT job_id, MAX(salary) FROM employees WHERE commission_pct IS NOT NULL GROUP BY job_id HAVING MAX(salary)>12000; # 查询领导编号大于102的每个领导下最低工资大于5000的领导编号和最低工资 SELECT manager_id, MIN(salary) FROM employees WHERE manager_id > 102 GROUP BY manager_id HAVING MIN(salary)>5000; # 多个字段分组 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) DESC;
-
连接查询:sql92和sql99语法
# sql92语法内连接语法: # 等值连接:产生交集部分 SELECT `name`,boyname FROM beauty, boys WHERE beauty.`boyfriend_id` = boys.`id`; SELECT department_name,d.manager_id,MIN(salary) FROM departments d, employees e WHERE e.`department_id` = d.`department_id` AND e.`commission_pct` IS NOT NULL GROUP BY department_name,d.manager_id; # 非等值连接 SELECT salary, grade_id FROM employees,job_grade WHERE salary BETWEEN lowerst_sal AND highest_sal; # 自连接 SELECT a.`employee_id`, b.`employee_id` FROM employees a, employees b WHERE a.`manager_id` = b.`employee_id`; SELECT country_id, COUNT(*) FROM departments d,locations l WHERE d.`location_id` = l.`location_id` GROUP BY l.`country_id` HAVING COUNT(*)>2;
# sql99内连接语法 #inner join SELECT last_name,department_name FROM employees e INNER JOIN departments d ON e.`department_id` = d.`department_id`; # 三表连接 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; # 非等值连接 # 自连接 SELECT e.last_name,m.last_name FROM employees e INNER JOIN employees m ON e.`manager_id` = m.`employee_id` WHERE e.`last_name` LIKE '%k%';
# 外连接,用于查询一个表中有另一个表中没有,结果为主表的全部记录 # 包括两部分:内连接(只要有相等就会显示) + 主表有但是从表没有的显示为null(筛选的时候用从表的主键) # 左外和右外交换表的顺序,可以实现同样的结果 # 一般是为了查询除了交集部分的不匹配的行 # left outer right outer SELECT `name`,boys.* FROM beauty LEFT OUTER JOIN boys ON beauty.`boyfriend_id` = boys.`id` WHERE boys.id IS NOT NULL; SELECT department_name FROM departments d LEFT OUTER JOIN employees e ON d.department_id = e.department_id WHERE e.employee_id IS NULL; # 查询部门名为SAL或者IT的员工信息,防止出现SAL部门没有员工 SELECT e.* FROM employees e RIGHT OUTER JOIN departments d ON e.`department_id` = d.`department_id` WHERE d.`department_name`= 'SAL' OR d.`department_name` = 'IT'; # full outer join,除了内连接结果,保留左和右边没有匹配的部分 # 交叉连接:就是笛卡尔乘积 SELECT `name`, boyname FROM beauty CROSS JOIN boys;
-
子查询
# 有了子查询后尽量不要用两表连接筛选了 # 如果是select嵌套select那么成为外查询/主查询 # 子查询,结果集为一个标量值 # where后边加select SELECT last_name,job_id,salary FROM employees WHERE salary=( SELECT MIN(salary) FROM employees ); # having后边加select SELECT department_id,MIN(salary) FROM employees GROUP BY department_id HAVING MIN(salary)>( SELECT MIN(salary) FROM employees WHERE department_id = 50 ); in/not in:可以改写为 =any / !=all ANY ALL # select后边加select # 查询是一条一条进行遍历的,所以在select后边的查询必须是一行一列 SELECT d.*,( SELECT COUNT(*) FROM employees e WHERE e.department_id = d.department_id )FROM departments d; # from后边加select,必须给新表起别名 SELECT ag_dep.*, jg.level FROM ( SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id ) ag_dep INNER JOIN job_grades jg ON ag_dep.ag BETWEEN jg.lowest_sal AND jg.highest_sal # exist SELECT d.department_name FROM departments d WHERE d.department_id IN ( SELECT e.department_id FROM employees e ); SELECT d.department_name FROM departments d WHERE EXISTS( SELECT * FROM employees e WHERE e.`department_id` = d.`department_id` ); SELECT bo.* FROM boys bo WHERE EXISTS( SELECT * FROM beauty b WHERE b.`boyfriend_id` = bo.`id` ); SELECT bo.* FROM boys bo WHERE bo.`id` IN ( SELECT b.`boyfriend_id` FROM beauty b );
-
分页查询
# 分页查询 limit offset,size; offset:要显示的起始索引,从0开始 size:要显示的条目数 # 分页公式: limit (page-1)*size,size; SELECT * FROM employees WHERE commission_pct IS NOT NULL ORDER BY salary DESC LIMIT 10;
# 一个经典的样例 # 查平均工资最高的部门的manager的信息 # 两个表的不同拼接会是不同结果 ( 如果是employee的department_id和department的department_id拼接,那么得到的结果是我们知道每个员工的部门详细信息 但是如果是employee的employee_id和department的manager_id拼接,那么得到的是我们知道每个部门领导人的详细信息 ) SELECT * FROM employees e INNER JOIN departments d ON e.`employee_id` = d.`manager_id` WHERE d.`department_id` = ( SELECT department_id FROM employees GROUP BY department_id ORDER BY AVG(salary) DESC LIMIT 1 );
-
联合查询
union 连接两个查询结果:查询结果来自于多个表,表之间没有连接关系,但是查询结果列数和列类型要一致 union all:可以包含两个表中的重复项
-