MySQL万字超详细笔记❗❗❗

2024-01-09 17:28

本文主要是介绍MySQL万字超详细笔记❗❗❗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MySQL

官网:https://dev.mysql.com/doc/refman/8.0/en/database-use.html
作用:管理逻辑上存在但物理上不存在的数据库和表等大数据环境中的静态资源。
它用于存储结果数据和其他小型数据,避免在大数据环境中存放。
要展示数据成果,只需连接到MySQL即可。
一、特点:
1.属于关系型数据库
常见的关系型数据库:sqlserver,mysql,oracle,db2…
关系数据库的标准:遵循T-SQL语言,以及通过表格结构化存储数据。
它们通过建立表间关系来实现复杂的数据查询和关联。
T-SQL的四部分: DCL(控制)
DDL(定义)
DML(操纵)
DQL(查询)

2.数据
数据以表格形式组织
存在表间关系
每列都有明确的数据类型和约束条件

3.库
系统库:information_schema 存储关于数据库、表、列、索引等结构和元数据信息的数据。
performance_schema 查询执行时间、锁定情况等。
sys 提供一些视图和存储过程
自定义库:
库,类似于文件夹,包含多个表。
表,可比作Excel表,由多个字段组成。每个字段包含名称、数据类型和约束。
对象,代表数据行。
数据,通过对象来表示和存储。

4.语法
;用于分隔一条sql语句,子查询作为一个内部的临时表存在,作为查询的一部分,不能用;结尾。

5.安全性
数据库锁:控制访问和修改数据库中的数据的并发需求。

6.分布式
有分布式存储(可面向集群),无分布式计算

表分区:将一个大表的数据分割成多个较小的部分,每个部分存储在不同的物理位置
分表:将数据分布到多个表中
分库:将数据分布到多个数据库中

二、DCL(创建用户与授权)
在数据库中创建一个自定义表,用于存储外部用户的信息。
向自定义用户表中插入外部用户的信息。
为不同用户分配不同的权限。

1.创建用户:
首先登陆为root用户
创建新用户命令示例:
CREATE USER 'henry'@'%' IDENTIFIED BY '111122';
%表示从任何主机连接,henry是用户名,111122是密码
2.获取当前登录用户的信息:
SELECT CURRENT_USER();可以查看当前登陆的用户和其连接来源
示例:root@localhost即表示是从本地以超级管理员身份登陆的。
3.用户权限控制:
root用户通常只用于本地权限,限制远程访问可增加安全性。
对于需要远程连接的情况,应创建新用户并分配相应权限。
4.远程用户创建及其权限授予:
创建远程用户示例:
CREATE USER 'your_remote_user'@'%' IDENTIFIED BY 'your_password';
授权示例:
GRANT SELECT,INSERT,UPDATE,DELETE ON your_database.* TO 'your_remote_user'@'%';

权限:全部`ALL PRIVILEGES`对象级增删改查`CREATE|DROP|ALTER|SHOW`数据级增删改查`INSERT|DETELE&TRUNCATE|UPDATE|SELECT`对象级操作主要关注数据库的结构和架构,而数据级操作关注的是表中存储的具体数据。授权一般授予都是数据级操作的权限。
权限的应用范围:`ON`关键字用来指定用户在特定主机上对特定数据库或表的权限示例:`ON DBNAME.TABLENAME TO USER@HOST`
使权限生效:`FLUSH PRIVILEGES;`激活所授权的内容

5.TCL(事务控制语言)
COMMIT表示提交数据,数据被永久保存
ROLLBACK用于数据回滚,可以撤销到最近的一次COMMIT的状态。

COMMIT;
SELECT * FROM TABLE_NAME;		有数据
SET autocommit = FALSE;
DELETE FROM TABLE_NAME;
SELECT * FROM TABLE_NAME;		无数据
ROLLBACK;
SELECT * FROM TABLE_NAME;		有数据

COMMIT后查询会显示数据
设置SET autocommit = FALSE;执行删除操作后,查询将不再显示数据
ROLLBACK;后查询将再次显示数据,显示回滚前的状态。

三、DDL(基本操作)
3.1 命名规则
使用小写字母命名库、表、字段,避免使用SQL关键字。

3.2 库的基本操作
创建库:CREATE DATABASE IF NOT EXISTS DATABASE_NAME;
删除库:DROP DATABASE IF EXISTS DATABASE_NAME;
使用库:USE DATABASE_NAME;
显示库信息:SHOW DATABASES;
查看当前库名:SELECT DATABASE();
修改库:通常涉及删除后再重新创建。
一般不建议改名,以免影响关联内容。主要用于添加约束,如外键。

添加外键约束
ALTER TABLE class   			指定修改的表为class	ADD CONSTRAINT fk_class_id		添加约束
FOREIGN KEY (fk_class_id)		
REFERENCES class (class_id);	

3.3 表的基本操作
字段
字段定义:字段名+数据类型+约束+字段批注
employee_id INT PRIMARY KEY COMMENT ‘员工id,主键’

创建表CREATE TABLE employees (id INT PRIMARY KEY,first_name VARCHAR(50),last_name VARCHAR(50),email VARCHAR(100));创建临时表WITH t AS();删除表
操作:删除表结构和数据,释放表空间。
命令:DROP TABLE IF EXISTS TABLE_NAME;清空表:
操作:清空所有数据,保留表结构。
命令:TRUNCATE TABLE TABLE_NAME;对比 TRUNCATE TABLE 和 DELETE FROM
相同点:都可以实现对表中所有数据的删除,同时保留表结构。
不同点:TRUNCATE TABLE:一旦执行此操作,表数据全部清除。同时,数据是不可以回滚的。(原理是在执行TRUNCATE之后立刻执行了一次COMMIT,此时进行回滚是回滚到删除后的状态)通常用于测试环境转为生产环境的情况。DELETE FROM:一旦执行此操作,表数据可以全部清除。(比较灵活,可以利用WHERE控制删除数据的范围)。同时,数据是可以实现回滚的。(也可以不实现回滚)当你使用DELETE语句删除表中的数据时,数据库管理系统将删除指定的行,但不会重置自增列主键的计数器。(即不会重复使用已经删除的主键值)
阿里开发规范:
【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但TRUNCATE无事务且不触发TRIGGER(TRIGGER用于一边删一边备份),
有可能造成事故,故不建议在开发代码中使用此语句。建议用DELETE。显示表:
SHOW TABLE_NAME;查询表结构:
DESC TABLE_NAME;【强制】备注:说明表用途
COMMENT "...";

3.4 数据类型
在这里插入图片描述

小结及选择建议:
关于字符串的选择:
任何字段如果为非负数,必须是 UNSIGNED
【强制】小数类型为 DECIMAL,禁止使用 FLOAT 和 DOUBLE。
说明:在存储的时候,FLOAT 和 DOUBLE 都存在精度损失的问题,很可能在比较值的时候,得
到不正确的结果。如果存储的数据范围超过 DECIMAL 的范围,建议将数据拆成整数和小数并 分开存储`。
【强制】如果存储的字符串长度几乎相等,使用 CHAR 定长字符串类型。
【强制】VARCHAR 是可变长字符串,不预先分配存储空间,长度不要超过 5000。如果存储长度大
于此值,定义字段类型为 TEXT,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

3.5 约束
1.数据类型(越小越好)
2.长度(定义数据带长度)
3.是否允许为空:(not) NULL(默认是允许为空的)
4.默认值:default VALUE -> (若没有给提供值,字段的值为默认值)
5.唯一键(唯一、可以为空):unique key
6.主键(唯一、不为空):primary key
主键的作用:主键是用来唯一标识表中的每一行记录的字段,可以用来快速查找和访问特定的记录。
单一和组合主键:单一主键用于唯一标识每一行,而组合主键则使用多个字段的组合来确保唯一性。组合主键通常用于解决多个字段都不足以唯一标识记录的情况。
主键的选择:选取没有实际业务意义的字段作为主键
主键的稳定性:尽量避免主键的变化。

主键和唯一键的区别:
可以有多个唯一键,但是只能有一个主键。
唯一键可能为空,主键不能为空。
主键可以作外键,唯一键不可以。
唯一键是为了限制不受主键约束的列上的数据的唯一性。

7.外键(表间关联):foreign key
外键的作用:外键是表中的一列,它建立了到另一个表中主键或唯一键的关系。
外键约束确保从表中的外键列的值必须存在于主表中的主键或唯一键列中。
主外键一致性:主外键的约束必须一致。
数据完整性:通过检查外键的值是否存在于被引用表的逐渐或者唯一键列中来判断是否拒用正确的关联关系。
从而实现正确的数据库操作。
外键列的值不允许为NULL。

外键与主从表
学生表(从表)中的班级信息必须来源于班级表(主表)中,要先有班级这张表。外键使得从表中的数据引用主表中的数据的时候,数据的完整性和一致性得到维护。⭐主从表
主从表是一种常见的数据库设计模式。
主表(Master Table)通常包含独特的数据,而从表(Slave Table)则包含引用主表主键的外键。
主表和从表之间的关系通常是一对多的关系。一是主表(一个主要实体),而多是主表(多个相关实体)。
在一对一的关系中,主从表可以任意指定。

8.零填充:zerofill
当该字段的值小于定义的长度时,会在该值的前面补上相应的0。
zerofill默认为int(10)
9.自增列:auto_increment
特点:唯一性
自增列必须是主键 ID INT AUTO_INCREMENT PRIMARY KEY

10.无符号数值:unsigned
有符号-128~+127,无符号为0~256

3.6 数据的完整性
数据的完整性是数据库设计的关键部分,它通过各种约束来实现。
数据的完整性包含域完整性,引用完整性和实体完整性三个方面。

     实体完整性:概念:确保表中每行数据的唯一性。手段:主键和唯一键。主键确保表中每行数据的唯一性。唯一键确保在指定列中的所有值都是唯一的。域完整性:概念:确保每个字段中的数据值满足一定的条件。标准:类型最小化,长度最短化(在确保足够的情况下,预留一些),格式正确。
​     	手段:数据类型长度限制非空约束默认值自增列有/无符号引用完整性
​     	概念:确保一个表可以依赖另一个表的值
​     	手段:外键。外键确保了一个表中的字段值必须在另一个表的列中有对应值。

DML(数据级)
​ 1.增 INSERT
​ 可缺省值(有默认值)的字段:自增列主键、允许为空的字段、设定默认值字段。
​ 插入数据:
单条或多条数据:INSERT INTO TABLE_NAME(FIELD1,FIELD2,...) VALUES(VALUE1,VALUE2,...) 多个值到单字段表:INSERT INTO TABLE_NAME(FIELD) VALUES(VALUE1),(VALUE2),(VALUE3);`
表间复制:
将A表中的数据复制到B表:
INSERT INTO TABLE_B(FIELD1, FIELD2, …)
SELECT FIELD1, FIELD2, … FROM TABLE_A;;

2.分表
为处理大量数据,根据规则或标准将数据分散到多个表中。
自增列设计:初始值递增,在每个表中自增的间隔相同。

​ 3.删 DELETE
​ 测试环境随便,生产环境禁用。
​ 不会删除用户数据,若真要删除用户数据前需要断开关联。
删除单条数据:DELETE FROM TABLE_NAME WHERE CONDITION(基于主键和唯一键)
删除多表连接数据:指定表实例进行删除

​ 4.改 UPDATE
更新数据:
​ UPDATE TABLE_NAME
​ SET FIELD1=‘VAL1’,FIELD2=‘VAL2’…FIELDN=‘VALN’
​ WHERE CONDITION;(基于主键或唯一键)
注意:执行更新操作时,唯一字段的新值不能与现有值重复。

5.DDL 和 DML DDL操作一旦执行,不可回滚。DML操作默认不可回滚,但若执行SET autocommit = FALSE后,可回滚。事务定义:由一到多个DML语句构成性质:要么成功要么回滚MySQL8新特性——DDL的原子化定义:DDL操作支持事务完整性,即要么成功要么回滚。改变了DDL操作一旦执行,不可回滚的限制。防止数据库的结构和数据受到部分完成的DDL操作的影响。例:CREATE DATABASE mytest;USE mytest;CREATE TABLE book1(book_id INT,book_nam VARCHAR(255));SHOW TABLES;DROP TABLE book1,book2;SHOW TABLES;即本身不存在book2这张表格,由于MySQL8的原子化特性,不完全成功就会进行回滚,因此最终结果并不会删除book1这张表格。

DQL
一 简单查询
1.逻辑运算符
and or not
2.简单查询

数据集类型:视图:存储SQL语句结果的虚拟表,仅用于查询,不存储实际数据。临时表:存储临时数据,数据库会话结束后自动删除。
查询格式:关键字换行以提高可读性。
查询语法:基本查询:SELECT 字段列表 FROM 表名 WHERE 条件;列选择:单个字段:SELECT FirstName FROM 表名;多字段组合:SELECT FirstName, LastName FROM 表名;字段部分:SELECT SUBSTRING(Email, 1, 5) FROM 表名;别名:用于简化字段或表的名称,可以省略AS关键字。条件查询:SELECT count(*) FROM 表名 WHERE 条件;条件语句:比较:=, <>, >, <, BETWEEN, IN空值判断:IS NULL, IS NOT NULL模糊匹配:LIKE,使用%(任意字符)和_(单个字符)作为通配符。
结果排序和限制:排序:ORDER BY 字段 [ASC|DESC]限制:LIMIT 起始位置, 数量
常见注意事项:浮点数值自动去除小数点后的零。区分查询的主次关系,例如区分“班级为主的查询”与“科目为主的查询”。  

二 分组(聚合)查询
1.单字段分组: 与多字段分组类似。
2.多字段分组: 使用 GROUP BY A, B 来对每个唯一的 (A, B) 对进行聚合操作。这意味着首先按 A 分组,然后在每个 A 分组内按 B 分组。这与 GROUP BY B, A 不同。
3.窗口分组: 使用 PARTITION BY 在查询结果的子集上执行计算。
4.结果集分组: 使用 GROUP BY 根据一个或多个字段对整个查询结果进行分组,并应用聚合函数(如 SUM, AVG, COUNT)以产生每个分组的单一聚合结果。
5.SELECT 子句: 当使用聚合函数时,SELECT 子句中通常只包含常量、聚合函数或 GROUP BY 指定的列名。
6.WHERE 与 HAVING 的区别:
WHERE: 用于原始数据表,不能使用聚合函数的别名,直接过滤数据。
HAVING: 在 GROUP BY 之后使用,用于过滤经过分组聚合后的数据表。
7.聚合非聚合列
A.为非聚合列添加聚合函数
SELECT MAX(COLUMN1) AS COL1 FROM SOURCE_TABLE;
B.将非聚合列作为分组列
SELECT A,B FROM SOURCE_TABLE GROUP BY A,B

聚合函数	纵向最大	MAX(EXP)纵向最小	MIN(EXP)纵向平均	AVG(EXP)纵向求和	SUM(EXP)纵向计数	COUNT(* | 1 | (DISTINCT) COL_NAME) 计算非空值数量纵向拼接	GROUP_CONCAT([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符']) 默认用逗号分隔。数据汇总	GROUP BY COLUMN1,COLUMN2 WITH ROLLUP;用于计算每个分组的结果,和汇总结果。SELECT year, IFNULL(month,"总体"), SUM(earnings) as total_earningsFROM salesGROUP BY year, month WITH ROLLUP;这段查询不仅提供每个年份下每个月份的收入总额,还会在每个年份的末尾提供该年份的总收入汇总,当`month`为NULL时,表示该行是一个汇总行,此时的`month`就会显示为总体(WITH ROLLUP和IFNULL(...,...)配合使用)
​		聚合函数可以嵌套使用 SUM(COUNT(*))行列转换 行转列:多行转成一列列转行:一列拆成多行 多列拆成多行行式数据库按行存储,列式数据库按列存储;列式数据库便于查找一类数据列式数据库在行列转换(数据透视)中发挥重要作用非透视行列转换使用 GROUP_CONCAT 和 CONCAT_WS 函数将每位学生的多个成绩合并为单个字段。selectS.stu_name,group_concat(concat_ws(':',U.subject_name,C.score) order by C.score desc) as stu_scoresfrom score_info Cinner join student_info Son C.fk_stu_id = S.stu_idinner join subject_info Uon C.fk_subject_id = U.subject_idgroup by S.stu_name;透视行列转换(将多行数据转化为一行 => 只是针对特定的作为字段的列 => 利用列式数据库)selectS.stu_name,(select score from score_info where fk.stu_id = S.stu_id and fk_subject_id=21) as JavaEE(select score from score_info where fk.stu_id = S.stu_id and fk_subject_id=22) as Hadoop,(select score from score_info where fk.stu_id = S.stu_id and fk_subject_id=23) as Spark,(select score from score_info where fk.stu_id = S.stu_id and fk_subject_id=24) as Python,(select score from score_info where fk.stu_id = S.stu_id and fk_subject_id=25) as Project变相分组selectS.stu_name,max(if(U,subject_name='JavaEE',score,0)) as JavaEE,max(if(U,subject_name='Hadoop',score,0)) as Hadoop,max(if(U,subject_name='Spark',score,0)) as Spark,max(if(U,subject_name='Python',score,0)) as Python,max(if(U,subject_name='Project',score,0)) as Project
子查询子查询别名的使用:FROM 子句中的子查询: 必须有别名,因为子查询在这里充当一个临时表,在主查询中作为表使用。SELECT, HAVING, WHERE 子句中的子查询: 一般返回单个值,通常不需要别名。但如果子查询的结果作为一列出现在 SELECT 子句中,通常需要别名以便于引用。子查询的应用场景:SELECT 子句: 作为计算字段的一部分,例如 (SELECT COUNT(*) FROM table) AS total。FROM 子句: 作为临时表,例如 FROM (SELECT * FROM table) AS temp。WHERE 子句: 用于存在性检查,例如 WHERE EXISTS (SELECT * FROM table WHERE condition)。HAVING 子句: 用于对聚合结果进行过滤。ORDER BY 和 LIMIT 子句: 用于对查询结果进行排序和限制。获取在LogicJava和javascript中取得前十名的学生信息和分数select *from (	selectfk_talent_id,scorefrom (select fk_talent_id,scorefrom yb_scorewhere subject in ('LogicJava','javascript')) as ALIA order by score desclimit 0,10;)获取LogicJava和javascript的同时出现在前二十名的学生信息和分数
解题思路:利用窗口函数
select fk_talent_id
from yb_score A
inner join (select subject,score from(select subject,score,dense_rank() over(partition by subject order by score desc range between unbounded preceding and unbounded following ) as rnkfrom yb_scorewhere subject in ('logicJava','javascript')) T where rnk = 20;
)B on A.score>= B.score and A.subject = B.subject
group by fk_talent_id
having count(*) = 2;
​	解题思路:获取两个科目第二十名学生的分数,科目,排名信息;将其与yb_score关联,并获取高于二十名分数的学生信息。
​		select 
​			fk_talent_id
​		from yb_score A
​		inner join(
​			select
​				subject,score,lj_rank,js_rank
​			from(	
​				select 
​					A.subject,A.score,
​					if(A.subject='LogicJava',@lj:=@lj+1,0)  lj_rank,
​					if(A.subject='javascript',@js:=@js+1,0) js_rank
​				from(
​					select
​						subject,score
​					from yb_score
​					where subject in ('LogicJava','javascript')
​					group by subject,score
​					order by subject,score desc
​				)A,(select @lj:=0,@js:=0)B	=> 子查询并不一定需要获取数据,也可以执行一些赋值操作。
​			)A
​			where subject='LogicJava' and lj_rank = 20
​			or subject='javascript' and js_rank = 20
​		)B on A.subject=B.subject and A.score>=B.score
​		group by fk_talent_id
​		having count(*)=2;
​		select subject,scorefrom yb_scorewhere subject in ('logicJava','javascript')  => 获取两个科目对应的倒序排名group by subject,scoreorder by subject,score desc;​		
​		select
​			A.subject,A.score
​			if(A.subject='logicJava',@lj:=@lj+1,0) lj_rank,
​			if(A.subject='javascript',@js:=@js+1,0) js_rank  => 声明并初始化@lj和@js,给其计数
​		from(
​			...
​		)A,(select @lj:=0,@js:=0)B	=> B表子查询仅作声明
​	selectsubject,score,lj_rank,js_rankfrom(												=> 获取两个科目第二十名学生的分数				...)where subject = 'logicJava' and lj_rank = 20or subject='javascript' and js_rank = 20select fk_talent_idfrom yb_score Ainner join(...												=> 获取大于第二十名分数的同时在两个科目的学生信息		)B on A.subject=B.subject and A.score>=B.score      => 此时的B相当于一个临时的表格,便于做数据筛选group by fk_talent_idhaving count(*)=2;​			
​	select * from 可以用于对内部查询的结果进一步添加操作 => 内部查询结果进行进一步的操作时,例如再次过滤、排序,或者与其他的查询结果进行联接等。
​		数据表可以由子查询代替	select fk_talent_id, count(*) as score_countfrom(//倒叙排 锁定前三十selectfk_talent_id,scorefrom(//两个科目select fk_talent_id,scorefrom yb_scorewhere subject in ('logicJava','javascript'))T order by score desc limit 0,30)T group by fk_talent_idhaving score_count=2;查询条件也可以是子查询select subject, scorefrom yb_scorewhere exists (select * from yb_score where subject='oop');select * from yb_scorewhere subject in('oop','javascript') and fk_talent_id in (select talent_id from yb_talentswhere talent_school in('南林','南邮'));

连接查询(多表联合查询)
ON 和 USING 的异同:
ON A.COLUMN_NAME = B.fk_COLUMN_NAME 等同于 USING(COLUMN_NAME)
不能直接在USING子句中添加额外条件,但在ON子句中可以添加额外条件

	WHERE 和 AND 的异同:WHERESELECT e.emp_no, s.to_dateFROM employees eLEFT JOIN salaries s ON e.emp_no = s.emp_noWHERE s.to_date = '9999-01-01';ANDSELECT e.emp_no, s.to_dateFROM employees eLEFT JOIN salaries s ON e.emp_no = s.emp_no AND s.to_date = '9999-01-01';`WHERE`的顺序是先关联再过滤,先进行LEFT JOIN,然后从结果集中过滤出`to_date`为'9999-01-01'的行。`AND`的顺序是在JOIN操作的时候就考虑了`to_date`条件,在左表中存在但是`to_date`不是'9999-01-01'的员工会显示为NULL。`WHERE`更适合筛选出`完全符合条件`的行,忽略不符合条件的数据。`AND`更适合保持关联查询中主表数据的完整性。数据库表的非传统关系:1.自引用关系:表中的记录与同一表中的其他记录存在关联。例如,一个员工和其他员工之间可能存在着上下级关系。CREATE TABLE Employees (employee_id INT PRIMARY KEY,name VARCHAR(255),manager_id INT, -- 指向上级员工的外键FOREIGN KEY (manager_id) REFERENCES Employees(employee_id));2.嵌套关系CREATE TABLE Articles (article_id INT PRIMARY KEY,title VARCHAR(255),comments JSON -- 嵌套的评论数据);-- 示例数据INSERT INTO Articles (article_id, title, comments)VALUES (1, '文章标题', '[{"comment": "很有见地的文章!", "author": "Alice", "timestamp": "2023-09-04 10:00:00"},{"comment": "我完全同意!", "author": "Bob", "timestamp": "2023-09-04 10:30:00"}]');

​ 多表查询的意义:
​ “每个xx的xx”:内连接订单表和产品表,可以查看每个订单的具体产品信息。
​ “关联数据”:将不同表中的相关数据关联起来,构建满足需求|完整的信息视图。
​ 同时可以将不同表中的数据进行组合。
​ “数据筛选”:便于进行基于"跨表条件"的数据筛选,减少冗余数据,排除无用数据。

多个数据来源
"FROM t1,t2"并未构建特定的表连接关系。

	多对多关系:两个表之间如果进行交叉关联(存在多对多关系),关联点的维度需要是一致的。// 书籍表CREATE TABLE Books (book_id INT PRIMARY KEY,title VARCHAR(255));// 作者表CREATE TABLE Authors (author_id INT PRIMARY KEY,name VARCHAR(255));// 作者-书籍关联表CREATE TABLE Author_Book (author_id INT,book_id INT,PRIMARY KEY (author_id, book_id),FOREIGN KEY (author_id) REFERENCES Authors(author_id),FOREIGN KEY (book_id) REFERENCES Books(book_id));


​ 笛卡尔积 cross join
定义:不需要任何连接条件,将A表中的每一行分别与B表中的每一行进行匹配合并。
​ 原因:1.关联点并非完全匹配
​ 2.两表内连接非唯一字段
​ 3.两表左外连接非唯一字段

后果:出现大量不合理数据
解决:直接进行等值关联
场景:通常用于没有明确的关联关系,但是需要两个表的所有记录进行组合的情况。例如足球比赛排期。

	内连接(交集) (inner) join定义:筛选出两表中符合条件的记录(交集)。当多行连续进行内连接的时候,示例如下:inner join stu_class_relation scr on C.fk_stu_id=scr.fk_stu_idinner join class_info A on A.class_id=scr.fk_class_idinner join subject_info J on J.subject_id=C.fk_subject_id	其实是有执行顺序的,两张表先"合并"为一张表,再在这张表的基础上继续进行"合并",不管是逻辑关联还是物理关联,只要关联点是在同一个维度上,都能起到约束作用。外连接(全集/差集)定义:保留主表中的所有记录,以及从表中与主表相符的记录,从表中与主表不符的记录用NULL表示。左外连接 left joinfrom 主 left join 从右外连接 right joinfrom 从 right join 主题目特征:所有学生的课程成绩:学生表作为外连接的主表补充:全外连接定义:本质是为了合并数据,返回在两表中所有的行,只在一个表中有的数据行缺的部分用NULL填充。主外键关系的多表连接查询不适用全外连接的原因:1.会提供一些不符合逻辑|没有必要的数据:没有订单的客户,没有客户的订单2.如果在Orders表中出现了不存在的客户的数据,左|右外连接可以筛选掉这些不合理的数据,而全外连接在合并数据的时候无法筛选掉这些不合理的数据。练习题:1.每个【部门】各有多少名【员工】select D.dept_name,count(*) as emp_countfrom dept_info Dleft join post_info Pon D.dept_id=P.fk_dept_idleft join emp_info Eon P.post_id=E.fk_post_idgroup by D.dept_id;2.带班最多的老师A、通过名词,已经名词的分析班:class_info老师:post_info + emp_info关系:emp_class_relationB、通过名词的关系,确定SQL语句的结构1、查老师-子查询select E.emp_id,E.emp_namefrom post_info Pinner join emp_info Eon P.post_id=E.fk_post_idand P.fk_dept_id=1;2、以查老师作为子查询,关联班级、班级关系表create view v_teacher_classasselectT.emp_name,count(*) as class_countfrom(select E.emp_id,E.emp_namefrom post_info Pinner join emp_info Eon P.post_id=E.fk_post_idand P.fk_dept_id=1)T left join emp_class_relation Ron T.emp_id=R.fk_emp_idleft join class_info Con C.class_id=R.fk_class_idgroup by T.emp_id;create temporary table t_teacher_class(selectT.emp_name,count(*) as class_countfrom(select E.emp_id,E.emp_namefrom post_info Pinner join emp_info Eon P.post_id=E.fk_post_idand P.fk_dept_id=1)T left join emp_class_relation Ron T.emp_id=R.fk_emp_idleft join class_info Con C.class_id=R.fk_class_idgroup by T.emp_id);   select A.emp_namefrom v_teacher_class Ainner join(select max(class_count) as max_count from v_teacher_class)B on A.class_count=B.max_count;select emp_namefrom v_teacher_classwhere class_count=(select max(class_count) as max_count from v_teacher_class);//select from yb_score Sleft join yb_talents Ton S.id=T.idgroup by subject

函数

判断空值ifnull(N,M) => 如果N为空,那么返回M,不为空则返回N本身。
数学函数+-		符号		sign(N) => 1/-1,1表示正值,-1表示负值绝对值		abs(N) => N/-N规约	向上取整 	ceil(M.N) 			=> M>0 ? M+1:M;向下取整	floor(M.N)			=> M>0 ? M:M-1;四舍五入	round(D[,N]) 		=> round(D) => 不保留小数,看第一位小数的值=> round(D,N) => 保留N位小数,看第N+1位小数的值格式化保留	format(D,N)	 		=> format(123456.789,2) => 123,456.789 将数字标准格式化之后保留N位小数保留精度    truncate(D,N)		=> truncate(123.456,2) => 123.45指对	自然幂运算  exp(N)	        	=> 2.718...^N(N可为小数)幂运算		pow(B,N)			=> B^N自然对数	ln(N)				=> ln(exp(2)) => 2对数		log(B,N)			=> log(2,2^2) => 2常用数	横向最大 	greatest(V1,V2,...) => 返回参数列表中的最大值横向最小	least(V1,V2,...)    => 返回参数列表中的最小值随机数		rand()				=> 返回0~1之间的随机小数(不包含0,1)伪随机		rand(seed)			=> 伪随机数:每次传入相同的种子获取的都是相同的系列数(是通过特定的算法获取的)进制转换	conv(N,fromBase,toBase) => 进制:2,8,10,16字符串函数ASCII码		ascii(char(1))		=> 返回字符的ASCII码(若传入字符串,则取第一个字符的ASCII码)字节长度	length(char(n))		=> 返回字符串字节长度(utf8mb4:三字节汉字)字符长度	char_length((char(n)))	=> 返回字符串字符长度拼接字符串	concat(char(n),int(4),decimal(3)) => 没有类型限制连字符拼接	concat_ws(separator,f1,f2...) 	=> 带分隔符的拼接找位置		FIND_IN_SET(SON,FATHER(逗号分隔)) => 利用逗号分隔的数字模拟string list,返回SON在FATHER中的下标(从1开始,不存在则返回0)LOCATE(SON,FATHER(不用逗号分隔)) => 返回FATHER中下标从1开始的第一个SON的第一个字符的下标(从1开始,不存在则返回0)LOCATE(SON,FATHER,POS) => 返回FATHER中下标从POS开始的第一个SON的第一个字符的下标POSITION(SON IN FATHER) => 返回FATHER中下标从1开始的第一个SON的第一个字符的下标(从1开始,不存在则返回0)SUBSTRING_INDEX('xxx,xxx,xxx,xxx',',',n) => 获取前n个数值(从n开始) => 获取第n个数值 SUBSTRING_INDEX(SUBSTRING_INDEX('xxx,xxx,xxx,xxx',',',n),',',N)select find_int_set('ab','xyzx,ab,cd') => 2locate('ab','xyzxabcd') => 5substring_index('ab,cd,efg,jk,lm',',',2) => ab,cd正则		regexp '...'		去除两端空格[l|r]trim(str)大小写转换	lower() upper()大小写比较	strcmp(stra,strb) => a>b? 1:a=b?0:-1;颠倒		reverse(str) => reverse('abc') => cba重复		repeat(str,times) => repeat('abc',3) => abcabcabc替换		replace(FILED_NAME,old_str,new_str)regexp_replace(source, pattern, replace_string)- source表示原始的字符串,pattern表示正则表达式,replace_string表示将正则匹配的部分替换为对应的字符串eg:获取'ab,cd,efg,hi'的数块数regexp_replace(source, '[^,]', ',')+1子串截取(下标从1开始,长度包括fromPos的字母)	substr(str,fromPos,len) => substr('abcdef',4) => defsubstr('abcdef',4,2) => deleft(str,len) 从左开始截取字符串,len是截取的长度right(str,len) 从第二个字母开始截取到字符串末尾,len是截取的长度加密(对用户的信息进行脱敏,直接拿加密的字段进行计算即可)		非对称加密	只可以加密,并且对同一个对象加密结果相同。md5(concat('prefix_salt','YOUR_PASSWORD','suffix_salt'));对称加密	既可以加密也可以解密。加密:select hex(aes_encrypt('123abc','yb12211'));=> D58445C73CFBE270BCA227014ACB9870解密:select cast(aes_decrypt(unhex('D58445C73CFBE270BCA227014ACB9870'),'yb12211') as char);=> 123abchex/unhex转化为16进制数之后,再通过cast的类型转化使其变为字符。cast ... as decimal/char(不可cast为int)
日期函数	在数据库中,日期格式的字符串可以等同于日期当前日期 	   		current_date() => 2023-07-25当前时间 	   		current_time() => 11:58:42当前日期和时间 		now()/current_timestamp(); => 2023-07-25 11:59:15当前时间戳	   		unix_timestamp(DATE); => 返回当前系统时间的时间戳(不传参数)/参数日期的时间戳(以s为单位)将时间戳转化为日期	from_unixtime(unix_timestamp(DATE)); => 返回长整数对应的日期格式(必须提供参数)日期提取 			extract(year|quarter|day|hour|minute|second from now());year(now()),month(now())... 只能用于完整日期的提取date_format(trans_date,'%Y-%m-%d') => 以特定形式提取日期:获取完整日期的'年-月'非完整日期的提取例如'2026-02'通常使用字符串函数RIGHT(s,n)	返回字符串 s 的后 n 个字符LEFT(s,n)	返回字符串 s 的前 n 个字符MID(s,n,len)	从字符串 s 的 n 位置截取长度为 len 的子字符串,同 SUBSTRING(s,n,len)LCASE(s)	将字符串 s 的所有字母变成小写字母日期判定			date like '2022-02%' 表示22年2月份的所有日期周日				dayofweek(now()); => 日-1 一-六2-7区分工作日和周末sum(dayofweek(submit_date) not in (1,7)) as weekend_cnt,sum(dayofweek(submit_date) in (1,7)) as working_cnt周日				weekday(now()); => 一-日 0-6月日				day|dayofmonth(date); => 月的第几天年日    			dayofyear(date) => 年的第几天年周				weekofyear(now()); => 年的第几周季周	            获取当前季度的第一天日期:SELECT CONCAT(DATE_FORMAT(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM  CURDATE()),1) + INTERVAL QUARTER(CURDATE())*3-3 MONTH),'%Y-%m-'),'01');   获取当前日期与第一天日期的天数差并且除7+1月周获取当前月份的第一天日期:SELECT CONCAT(DATE_FORMAT(LAST_DAY(CURRENT_DATE()),'%Y-%m-'),'01'); 获取当前日期与第一天日期的天数差并且除7+1日期计算  			adddate(date,interval(N UNIT));timestampadd(UNIT,num,date|datetime);日期天数差异	    timestampdiff(UNIT,fromDate|fromDatetime,toDate|toDateTime)(注意日期不能相减)	timestampdiff是后面减前面的,datediff是前面减后面的。
"EXPLAIN":查询语句的执行计划,以便了解查询的性能和优化方式。
EXPLAIN SELECT * FROM score_info;id: 查询的标识符。如果一个查询包含了子查询,那么主查询的id为1,子查询的id会递增。
select_type: 查询的类型。可能的值有:SIMPLE(简单查询,没有子查询或者union),PRIMARY(查询中最外层的查询),SUBQUERY(在select或者where子句中的子查询),DERIVED(在from子句中的子查询)等。
table: 输出结果集的表的名称。
partitions: 匹配的分区。
type: 表连接类型。最好的是system和const,最差的是ALL。
possible_keys: 表示可能应用在这张表中的索引。如果为空,那么没有可能的索引。
key: 实际选择的索引。如果为NULL,那么没有使用索引。
key_len: 使用的索引的长度。在不损失精确性的情况下,长度越短越好。
ref: 显示索引的哪一列被用于查找,可能的值有:一个常数,一个字段名或者一个函数。
rows: MySQL认为必须检查的用来找到所需行的行数。
filtered: 表示返回结果集的行占需要读到的行(rows列)的百分比。
Extra: 包含MySQL解决查询的一些额外信息。例如,使用了哪种类型的查询优化。“DESC”:获取表的结构信息
DESC TABLENAME;
	索引概述:索引是数据库查询加速的一种数据结构,类似于书的目录。它基于排序结构,支持高效查找,优化查询条件的搜索速度。创建索引:'CREATE INDEX'CREATE INDEX ix_product_description ON products(product_description);​		删除索引:'DROP INDEX'
​		DROP INDEX IX_NAME ON TABLE_NAME;
​		查表索引:'SHOW INDEX'SHOW INDEX FROM TABLE_NAME;索引分类:聚簇索引:用于主键,决定了数据在物理存储上的顺序。非聚簇索引:包括普通索引、唯一索引、组合索引等。适用场景:适用于频繁查询和大数据量的情况。优点:提升数据检索速度。 增强多表连接查询的效率。缺点:占用额外物理空间,影响数据存储。在数据频繁插入或删除时,维护索引的开销较大。索引的创建和维护随数据量增长而耗时增加。不宜使用索引的场景1.不常使用的列2.数据值很少或重复值很多的列3.包含大量NULL值的列4.LIKE语句中左侧有'%'时(LIKE '张%' ✔ LIKE '%张%' ❌)5.表连接字段6.唯一性差的字段7.频繁更新的字段 8.选择性高的字段本质:索引基于B树或B+树实现,用于存储表中的关键字(索引列值)和指向实际数据行的位置或指针。关键字有序存储(升序或降序)。聚集索引包含指向实际数据物理地址的指针,非聚集索引含主键值,需通过此主键值找到聚集索引(回表)。形式:索引占用表空间,用于存储和管理数据库数据及索引。优化:在长字符串字段上创建索引时,使用定长字符串作为索引可以提高效率。
变量变量类型:用户级变量(用@标识):主要在远程主机上使用全局变量(用@@或global标识):在虚拟机中使用,为所有用户共享局部变量:无特殊符号,应用于函数或存储过程中使用场景:查询操作:通常编写在存储过程中增删改操作:编写在函数中分支逻辑:出现在函数和存储过程中操作方法:设置用户级变量:示例:`set @val=0;`(不进行逻辑判断)累加操作:`set @val = @val + 2;`设置并赋值:`select @val:=11;`(若不加冒号,执行的是逻辑判断)查看变量值:`select @val;`设置全局变量:示例:`set @@val = 5;`查看特定全局变量:`show variables like '%character_set%';(用于显示包含特定字符的系统变量,如字符集设置)`局部变量的使用:原则:在函数头部声明所有变量声明方法:`declare var_name var_type default VALUE`示例:`declare var_1 int(8) default 5`
分支空值函数(`nullif`):用途:用于处理可能出现的空值语法:`nullif(V1,V2);`,当`V1=V2`时返回`NULL`,否则返回V1简单分支(三元运算符):用途:基于条件选择两个值中的一个。语法:if(CONDITION, v1, v2);如果CONDITION为真,则结果为v1,否则为v2。注意:在v1或v2处可以嵌套另一个if语句。条件符号:=:用作等于操作符。多分支(case-when-else-end):形式一:基于表达式的多值选择。语法:case EXP when V1 then do... when V2 then do... else do... end;形式二:基于条件的多值选择。语法:case when CONDITION1 then v1 when CONDITION2 then v2 else v3 end;注意事项:确保条件顺序正确,以避免逻辑错误。例如,当有多个条件关联时,应先检查更具体或更紧急的条件。多分支(if-elif-else-end if):用途:处理多个条件,每个条件对应不同的操作。语法:if CONDITION1 then do... elif CONDITION2 then do... else do... end if;
函数定义用途:主要用于增删改过程中。命名规则:通常在函数名前添加一个固定前缀。函数体特点:一般不使用@变量,以分号(';')结尾。声明函数时无需提交,但在调用函数时需要提交。创建函数语法create function FUNC_NAME(arg_type,arg_name) returns type;修改结束符delimiter //示例:delimiter //create function test(a int,b int) returns intdeterminstic begindeclare rst int default 0;if b=0 then set rst=NULL;else set rst=a/b;       函数体end if;return rst;end //delimiter ;注:`determinstic`关键字表示函数执行具有确定的结果,有利于缓存和优化。查看函数:状态查询:`show function status like 'FUNC_NAME%';`+------+-------+----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+| Db   | Name  | Type     | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |+------+-------+----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+| test | hello | FUNCTION | root@localhost | 2014-11-21 14:48:05 | 2014-11-21 14:48:05 | DEFINER       |         | latin1               | latin1_swedish_ci    | latin1_swedish_ci  |+------+-------+----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+查看函数信息:`show create function FUNC_NAME`;调用函数:`select func1(args...);``select count(*) as count;`删除函数:`drop function if exists FUNC_NAME;`设置函数创建信任用于允许用户创建函数:`set global log_bin_trust_function_creators=TRUE;`
存储过程
定义:预编译代码块,存储于数据库,用于重复调用。
参数:`in` 输入参数  `out` 输出参数  `inout` 输入/输出参数 可读取和修改
删除存储过程drop procedure if exists PROCEDURE_NAME
创建存储过程 createcreate procedure PROCEDURE_NAME(args...);
调用存储过程call PROCEDURE_NAME(args...);示例:定义一个分页查询的存储过程:drop procedure if exists pro_find_stu_by_page;delimiter ///*输入参数:想要查询的页码,一页的数据量输出参数:总页码*/create procedure pro_find_stu_by_page(in pageNo int,in pageSize int)# fromOffSet:对应页码的第一条数据的下标# 先获取合法的pageNobegindeclare fromOffSet int default 0;declare pageTotal int default (select ceil(count(*)/pageSize) from student_info);set pageNo = (casewhen pageNo<1 then 1when pageNo>pageTotal then pageTotalelse pageNoend);set fromOffSet = (pageNo-1)*pageSize;#     无需使用输出参数,而是通过select生成两个结果集。select pageTotal;selectstu_id,stu_name,stu_pid,stu_gender,add_province,add_city,stu_diploma,stu_type,stu_majorfrom student_infolimit fromOffSet,pageSize;end //delimiter ;call pro_find_stu_by_page(30,20);
循环死循环(`loop`)NAME:loop 创建循环leave NAME 跳出死循环iterate NAME 继续死循环示例:		drop function if exists func2;delimiter //create function f2(endSum int) returns int;determinsticbegindeclare i int default 1;declare proSum int default 0;MY_LOOP : loopset proSum = proSum + i;if proSum>=endSum then leave MY_LOOP;end if;set i = i + 1;end loop;return i;end//delimiter ;先判断后执行(`while`)✔示例:drop function if exists func2;delimiter //create function f2(endSum int) returns int;determinsticbegindeclare i int default 0;declare proSum int default 0;while proSum < endSum doset i = i + 1;set proSum = proSum + i;end while;return i;end //delimiter;先执行后判断(`repeat`) 示例:drop function if exists func2;delimiter //create function f2(endSum int) returns int;determinsticbegindeclare i int default 0;declare proSum int default 0;repeatset i = i + 1;set proSum = proSum + i;until proSum >= endSumend repeat;end//delimiter;区别:`while`循环在执行前判断条件,适用于可能不执行的场景。`repeat`循环至少执行一次,适用于至少需要一次执行的场景。`loop`提供更灵活的控制,通过 leave 明确指定退出点。


联合查询 
​		用途:扩展行
​		要求:字段数量和类型必须一致,字段名以第一张表为准。类型:
​			`UNION`:去重、排序、效率低。
​			`UNIONALL`:不去重,不排序,效率高。
​	列转行	
​		目的:将多列数据转换成行形式。
​		应用示例:将课程名和分数从多列变为单列SELECT stu_name, JavaEE AS score, 'JavaEE' AS subject FROM temp_wide_scoreUNION ALLSELECT stu_name, Hadoop AS score, 'Hadoop' AS subject FROM temp_wide_scoreUNION ALL...对每个科目分组,按分数降序排序SELECT subject,GROUP_CONCAT(DISTINCT score ORDER BY score DESC SEPARATOR '|') AS uq_scores_descFROM yb_scoreGROUP BY subject;
​	窗口函数​语法:WINDOW_FUNC[expr] OVER(PARTITION BY | ORDER BY | ...)先通过窗口规范对数据行进行分组,排序和计算,再进行聚合。​	作用:针对窗口范围内数据的计算和聚合操作,实现横向扩展。​	注意: 窗口函数一定需要在子查询中,即where子句需要在查询之外。窗口函数不可聚合。SELECT中存在非聚合列的情况下,使用窗口函数或者使用不影响计算结果的聚合函数聚合非聚合列。
​		  不可用DISTINCT。
​
​		序号函数:ROW_NUMBER()、RANK()(并列有影响)、DENSE_RANK()(并列无影响 ✔)排名还是用dense_rank(),不用rank()|limit。
​				  select FIELD_NAME,ROW_NUMBER() over(order by FIELD_NAME) as rk => FIELD_NAME(按照升序排序的值) ,rk(1,2,3...)
​		分布函数:PERCENT_RANK()、CUME_DIST()
​		前后函数:LAG(COLNAME,n,default)、LEAD(COLNAME,n,default)
​			第一个参数为列名,第二个参数为获取向上/下第n行,第三个参数为获取的数据行为Null时候取默认值。
​		头尾函数:FIRST_VALUE(expr)、LAST_VALUE(expr):开窗,窗口中显示expr经过排序后的首|尾值
​		其他函数:NTH_VALUE(expr,N)、NTILE(n)、
​				  SUM(FIELD_NAME):表示对当前行之前(包括当前行)的所有行对应字段的值求和,需要指定order by才能生效。
​								  如果不指定order by,默认为对该分组的所有值进行求和。
​				  SUM(CONDITION):统计符合条件的数量,注意如果为NULL,结果为0;(COUNT(COLUMN_NAME)则没有结果,因为COUNT自动过滤NULL)
​			 		CONDITION:CASE WHEN THEN...[<ROWS or RANGE clause> BETWEEN <Start expr> AND <End expr>]:定义窗口范围(如有partition by,则在分区内定义范围)Start expr | End expr :Current Row	当前行N preceding	前 n 行,n 为数字, 比如 2 Preceding 表示前2行unbounded preceding	开头N following	后N行,n 为数字, 比如 2 following 表示后2行unbounded following	结尾若不写即为rows between unbounded preceding and current rowROWS : 依据排序后的行号,取N行范围的数据。(可以通过构造ROW_NUMBER(ORDER BY ...))OVER(ORDER BY id RANGE BETWEEN 5 preceding AND current row)RANGE : 依据排序的列,获取排序列值范围的数据。OVER(ORDER BY salary RANGE BETWEEN 10000 preceding AND 10000 following)场景:求每个班、每个科目成绩的稳定程度。需求分析:稳定程度 -> 求欧氏距离(与平均值的差值) -> 将平均成绩扩展为窗口 avg(abs(每个学生的成绩-这个班这个科目的平均成绩)) 需要[班级][科目][成绩],不需要[学生信息],可以直接跳过student_info表直接将stu_class_relation与其相连代码:selectC.class_name,U.subject_name,I.score,avg(I.score) over(partition by C.class_name,U.subject_name) as avgByCUfrom score_info Iinner join subject_info Uon U.subject_id = I.fk_subject_id#inner join student_info Son S.stu_id = I.fk_stu_id# => 跳过物理关系选取逻辑关系inner join stu_class_relation Ron I.fk_stu_id = R.fk_stu_idinner join class Con R.fk_class_id = C.class_id此处使用窗口+聚合函数来实现,通过班级和科目进行分区,如果没有partition by,则默认作用于整个结果集partition by(a,b)表示每个a的每个b共享一个窗口场景:求每个班每个科目按成绩正序排每三个的平均成绩需求分析:为防止有数据缺项,长度为3的滑动窗口步长为1进行移动。=>如果所有数据参与计算,并且使用通用的计算方式,保证一定的数据量,结果就是有意义的。不通过排名来定义编号(可能出现并列的情况),通过行号来定义编号。班级 科目 成绩 1班级 科目 成绩 2班级 科目 成绩 3班级 科目 成绩 4班级 科目 成绩 5班级 科目 成绩 6场景:求每个班级每个科目的升序成绩和下一行的差值。需求分析;代码:over(partition by C.class_name,U.subject_name) 窗口粒度:每个班每个科目over(partition by C.class_name,U.subject_name,order by score asc)窗口粒度:从当前窗口的第一行至当前行(默认效果)over(partition by C.class_name,U.subject_name,order by score asc unbounded preceding unbounded following)窗口粒度:每个班级每个科目		selectC.class_name,U.subject_name,first_value(I.score) over win_cu as first_score,lag(I.score,1,-1) over win_cu as prev_score,I.score,lead(I.score,1,-1) over win_cu as next_score,last_value(I.score) over win_cu as last_scorefrom score_info Iinner join subject_info Uon U.subject_id = I.fk_subject_idinner join stu_class_relation Ron I.fk_stu_id = R.fk_stu_idinner join class_info Con R.fk_class_id = C.class_idwindow win_cu as(partition by C.class_name,U.subject_nameorder by I.scorerange between unbounded preceding and unbounded following);
递归函数语法:with recursive cte_name (col1,col2) as (-- 初始查询SELECT column1, column2, ...FROM tableWHERE condition-- 递归查询SELECT column1, column2, ...FROM cte_name(递归实现的关键)WHERE condition(指定递归的终止条件))
SQL查询优化:列裁剪:仅选择所需字段行裁剪:on | where | 分组聚合[去重]去重:group by | distinct列扩展:窗口函数 | 子查询SQL语句执行顺序——"fojwghsda聚ol"FROM 子句:检索数据表。ON子句:筛选出符合条件的行JOIN子句:表连接WHERE 子句:根据指定的条件筛选行。GROUP BY 子句:根据指定的列或表达式对行进行分组。/Partition by 子句HAVING 子句:根据条件筛选分组的行。SELECT 子句:选择将在结果集中返回的列或表达式。DISTINCT 子句:去重AS ALIAS 子句:别名聚合函数:计算汇总值,如 COUNT、SUM、AVG、MAX、MIN 等。ORDER BY 子句:排序。(ORDER BY 不能用于INNER JOIN(中的子查询))LIMIT/OFFSET 子句:限制结果集中返回的行数。inner join subject_info Uon U.subject_id = I.fk_subject_idinner join stu_class_relation Ron I.fk_stu_id = R.fk_stu_idinner join class_info Con R.fk_class_id = C.class_idwindow win_cu as(partition by C.class_name,U.subject_nameorder by I.scorerange between unbounded preceding and unbounded following);递归函数语法:with recursive cte_name (col1,col2) as (-- 初始查询SELECT column1, column2, ...FROM tableWHERE condition-- 递归查询SELECT column1, column2, ...FROM cte_name(递归实现的关键)WHERE condition(指定递归的终止条件))
SQL查询优化:列裁剪:仅选择所需字段行裁剪:on | where | 分组聚合[去重]去重:group by | distinct列扩展:窗口函数 | 子查询SQL语句执行顺序——"fojwghsda聚ol"FROM 子句:检索数据表。ON子句:筛选出符合条件的行JOIN子句:表连接WHERE 子句:根据指定的条件筛选行。GROUP BY 子句:根据指定的列或表达式对行进行分组。/Partition by 子句HAVING 子句:根据条件筛选分组的行。SELECT 子句:选择将在结果集中返回的列或表达式。DISTINCT 子句:去重AS ALIAS 子句:别名聚合函数:计算汇总值,如 COUNT、SUM、AVG、MAX、MIN 等。ORDER BY 子句:排序。(ORDER BY 不能用于INNER JOIN(中的子查询))LIMIT/OFFSET 子句:限制结果集中返回的行数。

这篇关于MySQL万字超详细笔记❗❗❗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/587870

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就