7.8 leetcode + 数据库

按照惯例先来三个leetcode,目前正在刷hot 100,算法方面的思路就是hot 100+🗡offer+labudong的算法小抄+回头继续刷leetcode。目前hot 100刷到了17题。算法是一个长期的项目需要坚持!!


 leetcode238 除以自身外的其他数的乘积,除法被ban了。这道题的思路其实和前缀和有异曲同工之妙,这里无非就是把和变成了积,另外值得注意的是,这里是除自己以外的所有,而是不只有前面的和,所以应当开两个前缀数组,准确来说是一个前缀,一个后缀,通过两个数组再来进行运算得到答案。

leetcode:41 缺失的第一个正数

这类问题的最大特点是,数值和自己的索引之间存在关联关系,因此要充分的利用这一点,在这个问题里面,通过这种类哈希关系,可以将数组置换成我们希望看到的样子。以此解决问题。另外特殊情况也要考虑进去。

leetcode 73:矩阵置零

这个没啥好说的,遍历一遍记录0行和0列,然后再遍历一遍进行赋值。


上周数据库方面主要学习了MySQL的基本执行过程,以及一些简单的SQL语法。那接下来就进行继续的学习。

1)MySQL的数据过滤
比较运算符:大于小于等于...在,不在等等

查询王者荣耀中生命值在5000到6000的英雄

看到都是一些脆脆鲨,还可以进行空置检查,看看表里面哪些是空的。

还有各种通配符等可以用来进行过滤操作。

2)SQL函数

函数顾名思义能够给我们提供一些数据处理的便捷操作。在SQL中主要提供了算数,字符串,日期,转换四类函数。

例如统计一下每个英雄的名字字数:

mysql> SELECT name,ROUND(LENGTH(name)/3,0) AS 名字字数 FROM heros;

例如,对于日期进行处理,提取英雄上线年份:

mysql> SELECT name,EXTRACT(YEAR FROM birthdate) FROM heros WHERE birthdate IS NOT NULL;

聚集函数:一共只有五个分别是COUNT,MAX,MIN,SUM,AVG

例如统计不同定位英雄的数量:

mysql> SELECT role_main,COUNT(*) FROM heros GROUP BY role_main ORDER BY COUNT(*) DESC;

可以利用多个指标进行分组,例如定位+职业可以诞生辅助坦克,辅助法师这样的。这样我们就可以得到许多的分组,如何对这些分组进行过滤?这里就要使用到HAVING关键字。

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...

这个顺序是不能变换的,变换之后在解析器这一步就无法进行语法语义检查。

最后的练习:

筛选最大生命值大于 6000 的英雄,按照主要定位进行分组,选择分组英雄数量大于 5 的分组,按照分组英雄数从高到低进行排序,并显示每个分组的英雄数量、主要定位和平均最大生命值

3)子查询

什么是子查询?虽然是一种嵌套查询的形式,不过我们依然可以依据子查询是否执行多次,从而将子查询划分为关联子查询和非关联子查询。

 在SELECT里面再SELECT 就是子查询,因为这里面只需要查询一次player表计算出平均值就可以了所以是非关联的。

但是如果统计每个队伍里面大于平均值身高的球员,就需要多次进行子查询,即关联子查询。主查询和子查询是关联的。

EXISTS 关键字,跟在WHERE后面过滤,查看这行数据是否存在在这个集合里面。 

EXISTS和NOT EXISTS子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT … FROM…), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。

例如查询某个选手是否得过分:

IN 和EXISTS: IN表示查询是否在集合里面,如果A表查询IN B里面,此时如果表B非常非常大,则需要不断地去循环查询是否存在要查询的这行数据,开销大。如果B很小,则IN的效率高。而对于EXISTS来说,A比较大的情况下,通过对B里面的数据取出来,去A里面的查询费事,但是A小的话则查询开销小。总结来说,IN是去B中对比,EXISTS是去A里面比较。

ANY顾名思义,代表任何一个,比一个大就行。别名SOME

ALL即所有。

子查询还可以作为计算字段,例如:

总的子查询是根据主查询的变化而变化的,主查询每次查询出来一行数据(理解),而子查询回根据情况决定是否重新查询。

练习:编写 SQL 语句,得到场均得分大于 20 的球员。场均得分从 player_score 表中获取,同时你需要输出球员的 ID、球员姓名以及所在球队的 ID 信息。

 每一次的筛选过滤都要从主查询的表开始去筛选。


好的,已经连接了SQL的最基本的一些操作。下面聊一聊表连接之间的事情:

首先我们来谈谈笛卡尔积:首先需要明确的是笛卡尔积是集合之间的操作,例如A集合{A1,A2,A3}

B集合{B1,B2}如果进行笛卡尔积,则结果为:{A1B1,A1B2,A2B1,A2B2,A3B1,A3B2},至于每个元素之间是什么操作,这就取决于我们的定义,在数据库来说每一个集合元素就是一行数据,而笛卡尔积就是简单的字段拼接。

例如,对team和player表进行拼接的话,就是完全的组合:

显然是不对的,这样的话大家都是三姓家奴了,因此需要对这个表进行过滤。这就引出了接下来的等值连接。其实就是用WHERE过滤了。

相对的,我们还可以有非等值连接,例如对队员的身高进行等级划分。

左右连接就更加简单了,但一般都是伴随着条件连接来说明这个问题的,可能A表中不能匹配到B表的信息,但是A表我又希望保留其所有内容因此诞生了左右连接之说。

语法就是LEFT JOIN和RIGHT JOIN。

自连接,通常在自我比较中使用,例如制作三队的循环对阵图:


数据库视图:

视图其实就是一个虚拟的表,其并不存在任何的数据,真正的数据只存在在表里面,抽象来说。视图的最大作用是把SQL查询语句进行了封装,使得可以在视图界面上进行数据读。另外视图也可以提供一些函数。

  1. 安全性:虚拟表是基于底层数据表的,我们在使用视图时,一般不会轻易通过视图对底层数据进行修改,即使是使用单表的视图,也会受到限制,比如计算字段,类型转换等是无法通过视图来对底层数据进行修改的,这也在一定程度上保证了数据表的数据安全性。同时,我们还可以针对不同用户开放不同的数据查询权限,比如人员薪酬是个敏感的字段,那么只给某个级别以上的人员开放,其他人的查询视图中则不提供这个字段。
  2. 简单清晰:视图是对 SQL 查询的封装,它可以将原本复杂的 SQL 查询简化,在编写好查询之后,我们就可以直接重用它而不必要知道基本的查询细节。同时我们还可以在视图之上再嵌套视图。这样就好比我们在进行模块化编程一样,不仅结构清晰,还提升了代码的复用率。

另外,我们也需要了解到视图是虚拟表,本身不存储数据,如果想要通过视图对底层数据表的数据进行修改也会受到很多限制,通常我们是把视图用于查询,也就是对 SQL 查询的一种封装。那么它和临时表又有什么区别呢?在实际工作中,我们可能会见到各种临时数据。比如你可能会问,如果我在做一个电商的系统,中间会有个购物车的功能,需要临时统计购物车中的商品和金额,那该怎么办呢?这里就需要用到临时表了,临时表是真实存在的数据表,不过它不用于长期存放数据,只为当前连接存在,关闭连接后,临时表就会自动释放。

 数据库存储过程:

存储过程其实就是对于SQL语句的封装,相较于视图,存储过程具有流程控制等等复杂语法,其只需要进行一次封装就可以一直执行。其也可以含有参数。具有以下优缺点:

优点:

首先存储过程可以一次编译多次使用。存储过程只在创造时进行编译,之后的使用都不需要重新编译,这就提升了 SQL 的执行效率。其次它可以减少开发工作量。还有一点,存储过程的安全性强,我们在设定存储过程的时候可以设置对用户的使用权限,最后它可以减少网络传输量,因为代码封装到存储过程中,每次使用只需要调用存储过程即可,这样就减少了网络传输量。

但是其在不同数据库之间的可移植性差,难以调试,不适合高并发场景,数据分库分表,储存过程需要额外维护。 

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值