SQL学习

  1. 原理

1、主键和外键区别:

主键:不能重复,唯一标识一条记录。比如:学生学号,市民身份证号。

外键:用于关联其他表,保持数据一致性。一个部门有多个员工,部门表里的员工号就是部门表的外键,关联于员工表。

2、主键与唯一索引区别:

a.本质:主键是约束,唯一索引是索引,主键是逻辑键,逻辑是索引键。

b.关系:

主键一定包含一个唯一索引,唯一索引不一定是主键

一个表最多一个主键,唯一索引可以有多个

唯一索引不能引用为外键,主键可以

3、Mysql的事物

1事物原理

数据库的事务是指一组sql语句组成的数据库逻辑处理单元,在这组的sql操作中,要么全部执行成功,要么全部执行失败。

这里的一组sql操作,举个简单又经典的例子就是转账,事务A中要进行转账,那么转出的账号要扣钱,转入的账号要加钱,这两个操作都必须同时执行成功,为了确保数据的一致性。

隐式事务

事务没有明显的开启和结束的标记,比如inset,updata,delete

显示事务

事务具有明显的开启和结束的标记,

前提:必须先设置自动提交功能为禁用 set autocommit=0;

步骤1:开启事务

set autocommit=0;

start transaction;可选的

步骤2:编写事务中的sql语句(select insert update delete)

语句1;

语句2;

步骤3:结束事务

commit;提交事务

rollback;回滚事务

savepoint 节点名;设置保存点

2事务的特性

Mysql中事务的四大特性简称为ACID,主要包含:「原子性(Atomicity)」「一致性(Consistent)」「隔离性(Isalotion)」「持久性(Durable)」

原子性

原子性是指事务的原子性操作,对数据的修改要么全部执行成功,要么全部失败,实现事务的原子性,是基于日志的Redo/Undo机制。

一致性

一致性是指执行事务前后的状态要一致,可以理解为数据一致性。

隔离性

隔离性侧重指事务之间相互隔离,不受影响,这个与事务设置的隔离级别有密切的关系。

持久性

持久性则是指在一个事务提交后,这个事务的状态会被持久化到数据库中,也就是事务提交,对数据的新增、更新将会持久化到数据库中。

总结

原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的。

3说一说Redo/Undo机制

3.1原理

Redo/Undo机制比较简单,它们将所有对数据的更新操作都写到日志中。

3.2作用

Redo log用来记录某数据块被修改后的值,可以用来恢复未写入 data file 的已成功事务更新的数据;Undo log是用来记录数据更新前的值,保证数据更新失败能够回滚。

假如数据库在执行的过程中,不小心崩了,可以通过改日志的方式,回滚之前已经执行成功的操作,实现事务的一致性。比如:假如某个时刻数据库崩溃,在崩溃之前有事务A和事务B在执行,事务A已经提交,而事务B还未提交。当数据库重启进行 crash-recovery 时,就会通过Redo log将已经提交事务的更改写到数据文件,而还没有提交的就通过Undo log进行roll back。

4.事务隔离级别

4.1原理

在Mysql中事务的隔离级别分为四大等级,「读未提交(READ UNCOMMITTED)、读提交 (READ COMMITTED)、可重复读 (REPEATABLE READ)、串行化 (SERIALIZABLE)」

4.2事务的并发性问题

读未提交会读到另一个事务的未提交的数据,产生脏读问题,读提交则解决了脏读的,出现了不可重复读,即在一个事务任意时刻读到的数据可能不一样,可能会受到其它事务对数据修改提交后的影响,一般是对于update的操作。

可重复读解决了之前不可重复读和脏读的问题,但是又带来了幻读的问题,幻读一般是针对inser操作。

4.3如何避免事务并发性问题?

4.常见约束

约束: 一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

4.1外键的约束作用

外键是该表与另一个表之间联接的字段 。

外键必须为另一个表中的主键 ,外键的用途是确保数据的完整性。

外键是用来控制数据库中数据的数据完整性的,就是当你对一个表的数据进行操作时,和他有关联的一个或更多表的数据能够同时发生改变,这就是外键的作用。

5.锁

乐观锁、悲观锁的实现以及具体的应用场景?

乐观锁

悲观锁

6.索引

7.SQL查询语句的执行顺序

第一步:from。FROM 才是 SQL 语句执行的第一步,并非 SELECT 。

第二步:on。筛选出满足ON 逻辑表达式的行。 是两表连接,左表右表都有的字段,加and再对连接条件进行筛选。

第三步:jion。JOIN 添加外部行

第四步:WHERE 聚合函数只能用在having里,不能用在where里


#错误示范
where
    datediff (date (max(start_time)), date (tvl.start_time)) <= 29
#正确
WHERE DATEDIFF(DATE((select max(start_time) FROM tb_user_video_log)), DATE(a.start_time)) <= 29

第五步:GROUP BY 分组

第六步: AGG_FUNC 计算聚合函数。SQL Aggregate 函数计算从列中取得的值,返回一个单一的值

第七步:WITH 应用

CUBE 和 ROLLUP 区别如下:

  • CUBE 生成的结果数据集显示了所选列中值的所有组合的聚合。

  • ROLLUP 生成的结果数据集显示了所选列中值的某一层次结构的聚合。

第八步:HAVING 应用

HAVING 语句在SQL中的主要作用与WHERE语句作用是相同的,但是HAVING是过滤聚合值,在 SQL 中增加 HAVING 子句原因就是,WHERE 关键字无法与聚合函数一起使用,HAVING子句主要和GROUP BY子句配合使用。

第九步:SELECT 选出指定列

第十步:DISTINCT 行去重

第十一步:ORDER BY 排列

第十二步:LIMIT/OFFSET 指定返回行

  1. 函数

2.1常见函数

  • limit函数

  • select * from job limit a,b:#无括号

  • limit 10 检索前10行, limit 0,10 检索前10行 效率高

  • limit 1,10 检索2-11行

  • limit 6,-1检索7-last

  • distinct函数

  • 去除每一行完全相同的行,某行有两列不同都不能去重。

时间函数

  • day函数

  • 去掉年月,只保留日

  • month函数

  • 去掉年日

  • year函数

  • 只保留年

  • date_add(date1, interval i day)

  • 比如:限定第二天来了的可以用date_add(date1, interval 1 day)=date2筛选

  • FIRST:返回第一个记录的值

  • LAST:返回最后一个记录的值

  • date_format (time, '%Y-%m')

  • TIMESTAMPDIFF

????在表格里用这个函数算和直接在编辑器用时间算结果不一样???SECOND

一个标量日期/时间函数,它返回指定日期部分的两个时间戳之间差异的整数计数。

指定单位可以是年,季度,月,星期,天数,小时,分钟,秒等等


{fn TIMESTAMPDIFF(interval-type,startdate,enddate)}

参数:
#interval-type - 返回值将表示的时间/日期间隔类型。
        FRAC_SECOND。表示间隔是毫秒
        SECOND。秒
        MINUTE。分钟
        HOUR。小时
        DAY。天
        WEEK。星期
        MONTH。月
        QUARTER。季度
        YEAR。年
#startdate - 时间戳值表达式。
#enddate - 将与 startdate 进行比较的时间戳值表达式。
  • DATEDIFF

仅用于返回两个日期的天数,不计算时间部分

应用:用途很广,比如用它来计算账单逾期的天数,或两个日期之间的天数。


DATEDIFF(end value, start value)
#第一个日期应该填结束日期,第二个参数应该填开始日期

如果参数传递的是日期-时间值,DATEDIFF函数仅将日期部分用于计算,
并忽略时间部分(只有值的日期部分参与计算)
-- 0
SELECT DATEDIFF('2022-04-30','2022-04-30 14:00:00');
-- 1
SELECT DATEDIFF('2022-04-30 13:00:00','2022-04-29 14:00:00');
-- 10
SELECT DATEDIFF('2017-06-25 09:34:21', '2017-06-15');

TIMESTAMPDIFF

DATEDIFF

时间是YYYY-MM-DD HH:MM:SS格式,在计算天数差时,使用两个函数计算出来的天数是不一样的

使用的是24小时制,即使是23:59:59,也不算做是一天

则是直接截取日期的部分相减

日期差值的计算方式相反,

end-start

TIMESTAMPDIFF(DAY,start,end)

DATEDIFF(end,start)


-- 2
SELECT DATEDIFF('2022-04-30 00:00:00','2022-04-28 23:59:59');
-- 4
SELECT TIMESTAMPDIFF(DAY,'2022-04-25 00:00:01', '2022-04-30 00:00:00');

单行函数

如concat、length、ifnull

分类:字符函数,数学函数,日期函数,其他函数,控制函数


字符函数

length:获取字节个数(utf-8一个汉字代表3个字节,gbk为2个字节)

concat 拼接字符串

instr 返回子串第一次出现的索引,如果找不到返回0

trim 去前后空格

upper #转大写

lower #转小写

lpad 左填充,指定元素填充,指定总长度

rpad 右填充,指定元素填充,指定总长度

replace 替换

substr #截取字符

substr(string, start_point, length*可选参数*)长度要一个一个数

substring_index()函数用来截取字符串

如 str=www.wiki.com

则 substring_index(str,'.',1) 处理的结果是:www

substring_index(str,'.',2) 得到的结果是:www.wiki

也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容,

相反,如果是负数,那么就是从右边开始数,第N个分隔符右边的所有内容。

数学函数

round 四舍五入

ceil 向上取整,返回大于等于该数的最小整数

floor 向下取整,返回小于等于该参数的最大整数

truncate 截断,小数点后面保留几位

mod 取余

count:MySQL中 COUNT在对列进行计数时不统计值为 null的条目

min\max 是统计全局最小|大的值,不是局部最值,比如10所学校里这所学校最值就不能用min等

其他函数

version 版本号

database 查看当前数据库

user 查看当前用户

流程控制函数if case

a.if函数

第一个参数为条件表达式,如果满足,返回第二个参数,不满足返回第三参数。

b.case函数

mysql中: 有判断的字段为简单case,无判断式为 搜索case函数。

case 要判断的字段或表达式(无这句话就是搜索case)

when 常量1 then 要显示的值1或语句1

when 常量2 then 要显示的值2或语句2

else 要显示的值n或语句n

end

*/

按从上到下的书写顺序计算每个WHEN子句的布尔表达式。

返回第一个取值为TRUE的布尔表达式所对应的结果表达式的值。

如果没有取值为TRUE的布尔表达式,则当指定了ELSE子句时,返回ELSE子句中指定的结果;

如果没有指定ELSE子句,则返回NULL。

窗口函数

作用:

可以在每一行的数据里直观的看到,截止到本行数据,统计数据是多少(最大值、最小值等)。同时可以看出每一行数据,对整体统计数据的影响,可以对数据库数据进行实时分析处理。

业务需求

“在每组内排名”

  1. 专用窗口函数

  1. rank, dense_rank, row_number等专用窗口函数

rank

如果有并列名次的行,会占用下一名次的位置。比如:4个同学排名,前三名并列,则名次为1,1,1,4.

dense_rank

如果有并列名次的行,不占用下一名次的位置。比如:4个同学排名,前三名并列,则名次为1,1,1,2.

row_number

不考虑并列名次的情况,比如:4个同学排名,前三名并列,则名次为1,2,3,4.

  1. 语法

<窗口函数> over (partition by <用于分组的列名>
                order by <用于排序的列名>)

#partition子句是可省略,省略就是不指定分组,只进行排序,但这样失去窗口函数意义,所以经常不这么做。


#例子:         
#rank是排序的函数,
#按“班级”分组(partition by班级)
#order by 排序
select *,
   rank() over (partition by 班级  
                 order by 成绩 desc) as ranking
from 班级表
  1. 开窗函数的框架限定
  • rows n perceding:从当前行到前n行(一共n+1行)

  • rang/rows between 边界规则1 and 边界规则2:

  • rang表示按照的范围进行定义框架,

  • rows表示按照的范围进行定义框架


#当前行往前2行+当前行+当前行往后2行(一共5行)
rows between 2 perceding and 2 following 

 #当前行的后1——>后3(共3行)
rows between 1 following 3 following

#从第一行到当前行
rows between unbounded preceding and current row 

SUM(like_cnt)OVER(PARTITION BY tag ORDER BY dt ROWS 6 PERCEDING)
#按照日期顺序,一行一行向下进行每日点赞数累加,每6+1行 为一个窗口框架进行数据累加
 
SUM(ret_cn)OVER(PARTITION BY tag ORDER BY dt ROWS 6 PERCEDING)
#按照日期顺序,进行大小比较,每7行为一个窗口框架,进行数据比较

group by

partiition by和rank函数

区别

分组汇总后改变了表的行数

不会减少原表中的行数

  1. 分组函数

  1. 作用:统计功能,又叫统计函数、聚合函数、组函数

  1. 分类:sum 求和、avg 平均值、max 最大值 、min 最小值 、count 计算个数

  1. 特点:

  1. sum、avg一般用于处理数值型

  1. max、min、count可以处理任何类型

  1. max,min对字符排序是根据字的字母顺序

  1. 以上分组函数都忽略null值

  1. 可以和distinct搭配实现去重的运算

  1. 和group by对比

  1. group by分组汇总后改变了表的行数,一行只有一个类别.

  1. GROUP BY可用于单个字段分组,也可用于多个字段分组

  1. 多列分组:多列取值都相同则为一组 

  1. partiition by和rank函数不会减少原表中的行数

  1. 查询语法

条件查询

语法

  • select 列 from 表 where 筛选条件

  • group by,order by 后面跟数字,指的是根据 select 后面查询的列进行分组、排序等,1 代表第一个列,2代表第二个列,依次类推

分类

按条件表达式:>,<, <>\!=,>=,<=

按逻辑表达式(用于连接条件表达式):and\&&,or\||,not\! and的优先级大于or

结果不去重用union all,去重就用 union\or

模糊查询:like ,between and,in,is null\is not null

like:一般和以下通配符搭配使用

%:任意多个字符,包含0字符

_:任意单个字符

[ ]:匹配[ ]中的任意一个字符(若要比较的字符是连续的,则可以用连字符“-”表 达 );

[^ ]:不匹配[ ]中的任意一个字符


#查看所有大学中带有北京的用户的信息
select device_id,age,university from user_profile
where  university like '%北京%';

#查询学生表中姓‘张’、姓‘李’和姓‘刘’的学生的情况。
SELECT * FROM 学生表 WHERE 姓名 LIKE '[张李刘]%’;

#查询学生表表中名字的第2个字为“小”或“大”的学生的姓名和学号。
SELECT 姓名,学号 FROM 学生表 WHERE 姓名 LIKE '_[小大]%';

#查询学生表中所有不姓“刘”的学生。
SELECT 姓名 FROM 学生 WHERE 姓名 NOT LIKE '刘%’;

#从学生表表中查询学号的最后一位不是2、3、5的学生信息。
SELECT * FROM 学生表 WHERE 学号 LIKE '%[^235]';

排序查询

语法:select 列表 from 表名 where 筛选条件 order by 排序的字段或者表达式;

特点:

默认升序,asc;desc代表降序;

order by 字句能支持 别名、单个字段、表达式、函数、多个字段

order by 字句排在查询语句最后,出limit字句外;

子查询

含义

  • 标量子查询(单行子查询) 标量子查询的值是一个值

  • 列子查询(多行子查询)

  • 行子查询(一行多列)

  • 表子查询结果充当一张表,要求必须起别名

语法

  • 子查询放在小括号里

  • 子查询一般放在条件右侧

  • 标量子查询一般配合单行操作符使用: >= .<=.<>

  • 列子查询一般搭配多行操作符:in、any、some、all

  • in/not in 返回列表中的任意一个

  • any/some 和子查询返回的某一个值进行比较

  • all 和子查询返回的所有值进行查询。

  • 子查询优先主查询

with as


with tmp  as (select * from B)

select * from  tmp

先执行select * from B拿到一个结果,将这个结果记录为tmp,再执行 select * from  tmp

应用场景

因with as 子查询仅执行一次,将结果存储在用户临时表中,提高查询性能,所以适合多次引用的场景,如:复杂的报表统计,分页查询,且需要拿到sum、count、avg这类结果作为筛选条件,对查询出的结果进行二次处理!

  1. 多表连接

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

因为执行顺序是先from 再select。

4.1分类

内连接:inner

外连接:左外 left【outer】 右外, right 【outer】,全外 full ,交叉连接 cross

4.2语法

select 列表

from表1

jion (inner jion\)表2 内连接inner可省略

on 连接条件 (and)

where 筛选条件 (连接之后的全表进行筛选)

group by 分组

having 筛选条件

order by 排序

limit 筛选

4.2.1内连接

a、等值连接

inner可省略


#案例1.查询员工名、部门名

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

b、非等值连接

连接语法:between and


#查询员工的工资级别

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

4.2.2外连接

作用:查询一个表有,另一个表没有的记录

特点:

1、外连接查询结果是主表的所有记录,重点是所有记录

从表有匹配的值则显示匹配值,无匹配值则显示null

2、left jion左边是主表,right jion右边是主表 ;不是on左右

3、外连接查询结果=内连接+主表有从表无

4、左外和右外可以交换两个表的顺序

4.3子查询

  1. 标量子查询(单行子查询)

  1. 列子查询(多行子查询)

  1. 行子查询(多列多行)

子查询放在小括号里,一般放在条件的右侧

单行子查询搭配单行操作符使用:

< >= <= = <>

列子查询搭配多行操作符使用:

in、any/some 、all

子查询的执行优先于主查询,主查询的条件遇到了子查询的结果

列子查询

多行操作符

in/not in 返回列表中的任意一个 # <>all =in

any/some 和子查询返回的某一个值进行比较

all 和子查询返回的所有值进行查询。

select后面的子查询使用,仅仅支持标量子查询

from后面的子查询使用,将子查询结果充当一张表,要求必须起别名

exists后面的子查询使用,能用exists的都能用in查询.

语法:

exists(完整的查询语句)

结果:

1或0

4.4 联合查询

应用场景:

要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时

特点:

  1. 要求多条查询语句的查询列数是一致的!(select 查的列一致。原始表列可以不一致。

  1. 要求多条查询语句的查询的每一列的类型和顺序最好一致

  1. union关键字默认去重,如果使用union all 可以包含重复项

  1. select 查的列一致。原始表列可以不一致

  1. union all 和order by的用法


SELECT DISTINCT a.id,a.username,a.mobile,FROM_UNIXTIME(a.time,'%Y/%m/%d') as _time,a.leader 
FROM (SELECT `id`,`username`,`mobile`,`time`,id AS leader 
    FROM `grouporder_leader` WHERE `courseid` = 21 AND `merchid` = 23 AND `status` = 1 
    UNION ALL 
    SELECT leadorderid,username,mobile,time,null 
    FROM `grouporder_partner` WHERE courseid=21 and status=1 and merchid=23
) AS a 
ORDER BY time DESC
  1. 业务逻辑+代码

  1. 2021年里有播放记录的每个视频的完播率。

视频完播率:

完成播放次数占总播放次数的比例。简单起见,结束观看时间与开始播放时间的差>=视频时长时,视为完成播放。复杂起见要考虑一个人可以重复看一个视频。

涨粉率

涨粉率=(加粉量 - 掉粉量) / 播放量

截止当前的总粉丝量

窗口函数

指标:

(video_id-视频ID, author-创作者ID, tag-类别标签, duration-视频时长(秒), release_time-发布时间)

(uid-用户ID, video_id-视频ID, start_time-开始观看时间, end_time-结束观看时间, if_follow-是否关注, if_like-是否点赞, if_retweet-是否转发, comment_id-评论ID)

每篇文章最大在看人数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值