文件储存
网页版爬虫数据库 : https://spidertools.cn/#/crypto
TEXT 文本储存
可以使用记事本打开
r #读取。
r+ #读写,文件指针放在文件的开头。
w #写入,覆盖原文件。
w+ #读写,覆盖原文件。
a #附加。
a+ #读写,文件指针放在文件的结尾。
rd / wd / ad # 读取、写入、追加二进制数据到二进制文件中
语法 | 描述 |
---|---|
f.close() | 关闭文件对象f,并将属性f.closed设置为True |
f.closed | 文件已关闭,则返回True |
f.encoding | bytes语str之间进行转换时使用的代码 |
f.read(count) | 从文件对象f中读取至多ciunt个字节,如果没有指定count,就读取从当前文件指针直至最后的每一个字节。 |
f.write(string) | 将str对象s写入到文件(二进制模式下写入bytrs) |
f.readline(count) | 读取下一(如果指定count,并在\n字符前满足这一数值,name最多读取count个字节),包括\n |
f.writelines(sep) | 批量写入 |
f.name | 文件对象f的文件名(如果有) |
f.flush() | 清空文件对象f,并将缓存中的内容写入到磁盘(如果有) |
with open('explore.text','a',encoding='utf-8') as file:file.write('\n'.join([question,author,answer]))file.write('\n' + '=' * 50 + '\n')'''=============================================='''def save_text(http,https,socks):'''将有用的信息进行保存'''http_csv = 'ip地址\http.csv'https_csv = 'ip地址\https.csv'socks_csv = 'ip地址\socks.csv'with open(http_csv,'w+') as p:for i in http:p.write("{:},{:}\n".format(i[0],i[1]))with open(https_csv,'w+') as ps:for o in https:ps.write("{:},{:}\n".format(o[0],o[1]))with open(socks_csv,'w+') as ks:for s in socks:ks.write("{:},{:}\n".format(s[0],s[1]))
JSON 文件储存
可以使用Word打开
JSON 数据需要用双引号来包围,不能使用单引号,否则会报错:
JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
import jsona = '''[{"name":"Bob",
"gender":"male",
"birthday":"1992-10-18"},{
"name":"Selina",
"gender":"female",
"birthday":"1995-10-18"}]''' # 创建 str 格式的一组数据data = json.loads(a) #使用loads()方法将字符串转换为JSON对象
data[0].get('name') #通过get()方法来获取name属性的值,等同 data[0]['name'],前者不会报错,如果没有会返回None
data[1].get('age',25) #通过get()方法来获取age属性的值,如果没有会返回默认值25
json.dumps(data) #将列表格式转换为字符串格式,等同str(data),前者可以接受关键字with open(wite,'w') as file:file.write(json.dumps(data,indent=2)) #使用dumps()将data转换为字符串格式,并添加关键字indent,保存后会首行缩进2格file.write(json.dumps(data,indent=2,ensure_ascii=False)) #将 ensure_ascii 设为 False 就可以保存中文字符
with open(‘E:\data.json’,‘w’,encoding = ‘utf-8’) as file: #这种设置编码的方式对json无效
CSV 文件储存
可以使用Excel打开,使用逗号分隔值或制表符分隔值
import csvwith open('E:\data.csv','w',encoding = 'utf-8') as file: #设置打开的编码格式为 utf-8writer = csv.witer(file,delimiter = '\t') #将分隔符更改为制表符writer.writerow(['id','name','age']) #单列表形式储存writer.writerows(['10001','Mike',20],['10002','BOd',22],['10003','Jordan',21]) #多列表形式储存'''字典形式储存'''
with open('E:\data.csv','w') as file:fieldnames = ['id','name','age'] #定义三个字段名writer = csv.DictWriter(file,fieldnames=fieldnames) #保存字典格式,并输入关键字fieldnames来确定字段名writer.writeheader() # 写入头信息,及['id','name','age']
writer.writerows([{'id':'1001','name':'Mike','age':'20'},{'id':'1002','name':'BOd','age':'22'},{'id':'1003','name':'Jordan','age':'21'}])'''用pandas读取CSV文件'''
import pandas as pddf = pd.read_csv('E:\data.csv')
print(df)
关系数据库储存
MySQL 的储存
https://www.runoob.com/mysql/mysql-tutorial.html 菜鸟教程
异步需要使用 aiomysql
SHOW 数据库名; # 查看数据库
USE 数据库名; #使用数据库
CREATE DATABASE 数据库名; #创建数据库
SQL分类
种类 | 功能 | 关键字 |
---|---|---|
DQL汇总(Data Query Language,数据查询语言) | 查询数据 | Select |
DML(Data Manipulation Language,数据操作语言) | 检索或者修改数据 | INSERT、UPDATE、DELETE |
DDL(Data Definition Language,数据定义语言) | 定义数据结构,如创建或删除数据库对象 | CREATE、TRUNCATE、DROP、ALTER |
DCL(Data Control Language,数据控制语言) | 定义数据库用户权限 | grant、revoke等 |
新建数据库
字符集:utf8mb4
排序规则:utf8mb4_general_ci 或者 utf8mb4_unicode_ci
SELECT 查询
SELECT * FROM dept; #查询数据表,* 为表的所有列(可以为一个或者多个,用逗号隔开), dapt为表名
SELECT dname AS d FROM dept; #使用 as 给列取别名
SELECT dname AS `as` FROM dept; # 使用关键字做为别名时,可以增加 ` ` 来进行标注
SELECT DISTINCT job FROM emp; # 使用 DISTINCT 进行去重
WHERE 限定查询
SELECT *|列名 FROM 表名 WHERE 条件;
限定查询
运算符 | 说明 |
---|---|
> | 大于 |
< | 小于 |
= | 等于 |
>= | 大于等于 |
<= | 小于等于 |
!=或者<> | 不等于 |
SELECT * FROM emp WHERE sal>1500; # 在 emp 表中查询 sal 值大于 1500 的项。
SELECT * FROM emp WHERE ename=‘ALLEN’; # 在 emp 表中查询 ename 值等于 ‘ALLEN’ 的项。(在windows中,列值不区分大小写,而在linux/ios中列值是区分大小写的)
SELECT * FROM emp WHERE BINARY ename=‘Allen’; #使用 BINARY 来使 Windows 中区分大小写。
IS NULL和IS NOT NULL
IS NULL #不占用空间的
**IS NOT NULL ** #占用空间的,包括空格
SELECT ename FROM emp WHERE comm IS NOT NULL; # 查询 comm 列中占用了空间的项
SELECT ename FROM emp WHERE comm IS NULL; # 查询 comm 列中不占用空间的项
SELECT ename FROM emp WHERE ename !=’ '; #查询 cname 列中所有不是空格(’ ')和空(NULL)的项
AND和OR、NOT
SELECT * FROM emp WHERE sal>1500 AND comm IS NOT NULL; #使用 AND 同时限制 sal>1500 和 comm IS NOT NULL ,需要同时满足
SELECT * FROM emp WHERE sal BETWEEN 1500 AND 3000; #使用 BETWEEN AND 限制满足大于等于 1500 和小于等于 3000 的项
**SELECT * FROM emp WHERE sal>1500 OR comm IS NOT NULL; ** #使用 OR 限制 sal>1500 和 comm IS NOT NULL ,需要满足其中一个
SELECT * FROM emp WHERE NOT (sal>1500 OR comm IS NOT NULL); #使用 NOT 对限制 sal>1500 和 comm IS NOT NULL 进行取反
SELECT * FROM emp WHERE hiredate BETWEEN ‘1981-10-17’ AND ‘1985-12-17’; #日期查询需要是日期格式。
IN 和 NOT IN
SELECT * FROM emp WHERE empno IN(7369,7499,7521); #查询 empno 值为 7369,7499,7521 的项
SELECT * FROM emp WHERE empno NOT IN(7369,7499,7521); #查询 empno 值不为7369,7499,7521 的项
LIKE 模糊查询
SELECT * FROM emp WHERE ename LIKE ‘_M%’; #查询 ename 中第二个字符是 M 的项(LIKE是用来进行模糊匹配的,_ 匹配一个字符,% 匹配0个或多个字符)
ORDER BY 排序
SELECT * FROM emp WHERE sal>1500 ORDER BY sal; #查询 sal>1500 的项,并进行排序(默认为升序)
SELECT * FROM emp WHERE sal>1500 ORDER BY sal DESC; #查询 sal>1500 的项,并进行降序排序(使用 DESC 进行降序排序)
SELECT * FROM emp WHERE sal>1500 ORDER BY sal DESC, hiredate ASC ; #先对 sal 进行降序排序,然后对 hiredate 进行升序排序。(多重排序)
DML 数据操作
功能:检索或者修改数据
关键字:INSERT、UPDATE、DELETE
INSERT(插入)
单一数据插入
语法1:INSERT INTO 表名(列名,列名,列名) VALUES(值,值,值);
语法2:INSERT INTO 表名 VALUES (值,值,值);
注意:你输入几个列名就插入几个值,列名和值的位置需要一一对应,如果你使用第二种结构,不写列名,就要保证后面的赋值个数覆盖了表中所有的列
示例:
INSERT INTO myemp(empno) VALUES(7788);
INSERT INTO myemp VALUES(7788,NULL,NULL,NULL,NULL...);
批量数据插入
语法:INSERT INTO 表名 SELECT 字段列表 FROM 表名 WHERE条件;
注意:INSERT表和SELECT表结果集的列数、列序、数据类型必须要一致
示例:
INSERT INTO TESR SELECT * FROM emp;
INSERT INTO TESR(deptno,dname,loc) SELECT * FROM dept; -- 将dept表插入到TESR表中
INSERT INTO TESR(deptno,dname,loc) SELECT deptno,dname,loc FROM dept;
-- 手动插入多行-在TESR表中的depto,dname,loc属性插入值
INSERT INTO TESR(deptno,dname,loc) VALUES
(61,'A','AA'),
(62,'B','BB'),
(63,'C','');
实例:
-- 插入数据
INSERT INTO tt(pid,`name`,job) VALUES
(01,'孟东亮','服务主管'),
(02,'伍增荣','高级领班'),
(03,'罗渝川','领班'),
(04,'官佳珍','领班');
UPDATE(修改)
语法:UPDATE 表名 SET 要修改的字段1=新值,要修改的字段2=新值,... [WHERE 条件];
UPDATE myemp SET comm=100 WHERE empno=7896; -- 将 myemp 表中 empno 为78996的项内 comm 的值改为100
UPDATE tesr SET dname='luo',loc='luo' WHERE deptno=12;
UPDATE TESR SET loc='111'; -- 将TESR表中的loc列全部改为111
UPDATE `学员基本信息表` SET sex='男' WHERE pid IN(2,3,4,5,6,7,9,10,11,12,13);
UPDATE `学员基本信息表` SET job='保洁员' WHERE pid IN(14,15,16);
DELETE(删除)
语法:DELETE FROM 表名 [WHERE 条件];
DELETE FROM TESR WHERE deptno=62; -- 将TESR表中,deptno=62的这一条记录删除
DELETE FROM TESR WHERE deptno IN(61,63); -- 删除多行
DELETE FROM TESR; -- 删除表
DDL 数据定义语言
导入数据表
语法:LOAD DATA INFILE 要导入的文件路径,INTO TABLE 表名 FIELDS TERMINATED BY 分割字段方式(这里默认是逗号,可以更改为其他的分割方式)ENCLOSED BY 分号分割,默认就行 LINES TERMINATED BY 换行 IGNORE 1 ROWS 忽略第一行(本例中第一行为数据库中对应的字段,如果你的文件中第一行就是数据的话,就不要忽略第一行了)。
LOAD DATA INFILE 'D:\\Document\\Download\\test0142.csv' INTO TABLE city_china FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS ;
创建数据表
功能:定义数据结构,如创建或删除数据库对象
关键字:CREATE、TRUNCATE、DROP、ALTER
语法1:CREATE TABLE 表名(
字段名1 字段类型 [DEFAULT 默认值],
字段名2 字段类型 [DEFAULT 默认值],
字名3 字段类型 [DEFAULT 默认值]
...
字段名n 字段类型 [DEFAULT 默认值]
) ENGINE=引擎名称 CHARSET='编码方式';
语法2:CREATE TABLE 表名 AS (查询);
注意:当查询不成立时,如1=2,则值复制表结构,不复制表数据
CREATE TABLE tt(abc int, string varchar(5), test int DEFAULT 6) ENGINE=INNODB CHARSET='utf-8'; -- string varchar(5) 表示 string 为varchar类型,字符长度为5 ;test int DEFAULT 6 表示 test 为int格式,默认值为6
常见的数据类型
类型 | 大小 | 范围 | 描述 |
---|---|---|---|
INT或INTEGER | 4字节 | (-2147483648,2147483647) | 大整数值 |
FLOAT | 4字节 | (-3.402823466E+38,-1.175494351E-38) 0 (1.175494351E-38,3.402823466E+38) | 单精度浮点数值 |
DOUBLE | 8字节 | (-1.7976931348623157E+308,-2.2250738585072014E-308) 0 (2.2250738585072014E-308,1.7976931348623157E+308) | 双精度浮点数值 |
CHAR | 0-255字节 | 无 | 定长字符串 |
VARCHAR | 0-65535字节 | 无 | 定长字符串 |
DATE | 3字节 | 1000-01-01~9999-12-31 | 日期值 |
DATETIME | 8字节 | 1000-01-01 00:00:00~9999-12-31 23:59:59 | 混合日期和时间值 |
数据类型选取规则
类型 | 比较 |
---|---|
整数类型和浮点数类型 | 如果要表示小数只能用浮点数类型,整数类型不能表示小数。 浮点类型DOUBLE精度比FLOAT类型高,如果需要精度到10位以上,就应该选择DOUBLE类型。 |
浮点数类型和定点数类型 | 对于精度要求高的时候需要使用定点数存,因为定点数内部是以字符串形式储存 |
CHAR类型和VARCHAR类型和TEXT类型 | CHAR定长字符串,占用空间大,速度快。 VARCHAR变长字符串,占用空间小,速度慢。 TEXT类型是一种特殊字符串类型。只能保存字符数据,而不能有默认值。 它们3个存储和检索数据方式都不一样,数据检索的效率CHAR>VARCHAR>TEXT。 CHAR在保存的时候,后面会用空格填充到指定的长度,在检索的时候后面的空格会去掉。 VARCHAR在保存的时候,不进行填充。当值保存和检索时尾部的空格任然保留。 |
日期和时间类型 | YEAR只保存年份,占用空间小。 其它和日期时间有关的可以通过整型保存时间戳,方便计算。 |
补充:一般我们的整型的定义不用在后面去加它的一个长度。少用像test、blob那种比较长,比较不可控的类型,尽量使用CHAR或者VARCHAR来做,因为它们的检索效率是不一样的。除此之外要注意的是VACHAR里面的N指代的是数据的字符长度,而不是字节数。在存一些精度特别高的数据的时候,不管是使用float还是用的double,它因为浮点数的原则问题就和python一样始终会有精度上的缺陷,这个时候你可以使用定点数的方式存储(decimal格式)
实例:
CREATE TABLE student(
pid VARCHAR(18), -- 表示人的编号
`name` VARCHAR(30), -- 表示人的姓名
age INT(3), -- 表示人的年龄
brithdate DATE, -- 表示出生日期
sex VARCHAR(2) DEFAULT '男' -- 表示性别,默认值为'男'
);
CREATE index pf ON player_attributes(preferred_foot); #创建一个索引,能够加快后续的检索速度 pf为检索类容,player_attributes为表名,preferred_foot为检索项目
常用的五类约束
名称 | 含义 |
---|---|
NOT NULL | 非空约束,指定某列不为空 |
UNIQUE | 唯一约束,指定某类列和几列组合的数据不能重复 |
PRIMARY KEY | 主键约束,指定某列的数据不能重复,值必须唯一 |
FOREIGN KEY | 外键,指定该列记录属于主表中的一条记录,值参照另一条数据 |
DEFAULT | 默认约束,当没有给对应列的值的时候,默认的内容 |
注意:在MySQL中不支持CHECK约束,但可以使用CHECK约束,而没有任何效果
CREATE TABLE student2(
pid INT PRIMARY KEY, -- 表示人的编号 (主约束)
`name` VARCHAR(30) UNIQUE NOT NULL, -- 表示人的姓名 (唯一约束,非空约束)
age INT(3) NOT NULL, -- 表示人的年龄 (非空约束)
brithdate DATE, -- 表示出生日期
sex VARCHAR(2) DEFAULT '男' -- 表示性别,默认值为'男'
);
auto_increment #设置自动增加属性
auto_increment=n #指定一个自增的初始值n
外键约束
在创建表的时候进行添加:
语法:[CONSTRAINT symbol] FOREIGN KEY (主表字段) REFERENCES 从表(从表字段);
FOREIGN KEY (pid) REFERENCES student2(pid) # 新建的表 pid 列与 student2 表 pid 列进行关联
CONSTRAINT haha FOREIGN KEY (`name`) REFERENCES student2(`name`) # 使用 CONSTRAINT 对外键名进行更改
对于创建好的表,继续修改表的结构来添加外键 :
语法:ALTER TABLE 主表 ADD [CONSTRAINT symbol] FOREIGN KEY(主表字段) REFERENCES 从表(从表字段);
实例:
-- 创建部门基本信息表
CREATE TABLE tt(
pid INT UNIQUE NOT NULL, -- 编号(int类型,唯一及非空约束)
`name` VARCHAR(30) PRIMARY KEY, -- 姓名(VARCHAR类型,长度为30,主约束)
sex VARCHAR(2) DEFAULT('女'), -- 性别(VARCHAR类型,长度为2,默认值为“女”)
dname VARCHAR(50) DEFAULT('服务保洁部服务组'), -- 部门(VARCHAR类型,长度为50,默认值为“服务保洁部服务组”)
job VARCHAR(30)); -- 职位(VARCHAR类型,长度为30)
ALTER (修改表)
功能 | 语法 |
---|---|
增加表的字段 | ALTER TABLE 表名称 ADD(列名称 数据类型 DEFAULT 默认值); |
删除某一列 | ALTER TABLE 表名称 DROP 列名称; |
给表重新命名 | ALTER TABLE 表名称 RENAME 新表名字; |
添加约束 | ALTER TABLE 表名称 ADD CONSTRAINT 约束名 约束; |
删除约束 | ALTER TABLE 表名称 DROP CONSTRAINT 约束名; |
ALTER TABLE student ADD CONSTRAINT lala FOREIGN KEY (name
) REFERENCES student2(name
); # 用ALTER 语句增加一个外键
ALTER TABLE tablemoney ADD CHECK (money>0); # 限定金额大于0
ALTER TABLE tablemoney ADD CHECK (rate>0 and rate<4)
ALTER TABLE tablemoney ADD CHECK (rate IN (1,2,3)) # 规定难度级别,只能为1,2,3
ALTER TABLE tablemoney ADD CHECK (uname like’A%') #必须以A开头的
DROP (删除表)
语法:DROP TABLE <表名>;
DROP TABLE person; # 删除表名为person的表
创建表、插入数据、修改数据实例:
-- 创建部门基本信息表
CREATE TABLE `部门人员基本信息`(
pid INT UNIQUE NOT NULL auto_increment, -- 编号(int类型,唯一及非空约束)
`name` VARCHAR(30) PRIMARY KEY, -- 姓名(VARCHAR类型,长度为30,主约束)
sex VARCHAR(2) DEFAULT('女'), -- 性别(VARCHAR类型,长度为2,默认值为“女”)
dname VARCHAR(50) DEFAULT('服务保洁部服务组'), -- 部门(VARCHAR类型,长度为50,默认值为“服务保洁部服务组”)
job VARCHAR(30), -- 职位(VARCHAR类型,长度为30)
tel BIGINT(11) UNIQUE); -- 插入数据
INSERT INTO `部门人员基本信息`(pid,`name`,job,tel) VALUES
(01,'孟东亮','服务主管',16659075935),
(02,'伍增荣','高级领班',13143205828),
(03,'罗渝川','领班',15723051314),
(04,'官佳珍','领班',18200758592),
(05,'谢伟龙','员工',18814011708),
(06,'温景霞','员工',15876319784),
(07,'江静怡','员工',14718365136);-- 修改数据
UPDATE `部门人员基本信息` SET sex='男' WHERE pid IN(2,3,5);CREATE TABLE `学员基本信息表`(
pid int UNIQUE NOT NULL,
`name` VARCHAR(30) PRIMARY KEY,
sex VARCHAR(2) DEFAULT('女'), -- 性别(VARCHAR类型,长度为2,默认值为“女”)
dname VARCHAR(50) DEFAULT('服务保洁部服务组'), -- 部门(VARCHAR类型,长度为50,默认值为“服务保洁部服务组”)
job VARCHAR(30) DEFAULT('学员'), -- 职位(VARCHAR类型,长度为30)
tel BIGINT(15) UNIQUE); INSERT INTO `学员基本信息表`(pid,`name`,tel) VALUES
(1,'杨佳慧',18922842063),
(2,'杨榆',13510598604),
(3,'张永钤',17780119952),
(4,'雷奇',18681490921),
(6,'曾渝敏',14774735437),
(7,'蓝林荣',17875764983),
(5,'周慧铭',13723721976),
(8,'况蕾',18807425813),
(9,'陈周沂',13417607122),
(10,'杨侃',18152641986),
(11,'李旌扬',18033081862),
(12,'陈敏武',13322762903),
(13,'曾锦涛',13242946460),
(14,'贾瑞华',13622364972),
(15,'郭秀兰',19974231328),
(16,'胡足足',13689575311);UPDATE `学员基本信息表` SET sex='男' WHERE pid IN(2,3,4,5,6,7,9,10,11,12,13);
UPDATE `学员基本信息表` SET job='保洁员' WHERE pid IN(14,15,16);INSERT INTO `部门人员基本信息`(`name`,sex,dname,job,tel)
SELECT `name`,sex,dname,job,tel FROM `学员基本信息表`; -- 将后表的数据插入的前表中ALTER TABLE `部门人员基本信息` RENAME `部门人员信息表`; -- 更改表名SELECT * FROM `部门人员信息表` ORDER BY pid; -- 按pid进行升序排序
SELECT 函数
字符串函数
字符串拼接:concat(str1,str2,…)
SELECT ename,job,CONCAT(ename,‘+’,job) FROM emp; # 表emp中的ename属性值和job属性值使用加号进行拼接
字符串长度:length(str)
SELECT ename,LENGTH(ename) FROM emp; # 求表emp中neame属性值的长度
数学函数
绝对值:abs(n)
SELECT ABS(5.6); #求5.6的绝对值
截取数值:trunc(n)
SELECT TRUNCATE(5.5558,3); # 小数点后保留3位
四舍五入:round(n,d)
SELECT ROUND(5.5558,3); # 让小数点后只保留三位数字(这个操作是会四舍五入的)
日期函数
当前时间:now()
格式化:date_format(date,format)
SELECT DATE_FORMAT(‘2008-08-08’,“%Y年 %m月 %d日”); #对日期进行格式化
返回天数:to_days(date)
IFNULL(expr1,expr2)函数
如果expr1不是NULL,IFNULL返回expr1,否则返回expr2
主要解决如果表达式中有空值会干扰计算的问题
SELECT ename,sal+IFNULL(comm,0) FROM emp; #使用 IFNULL 对 comm 中的空值进行处理,如果为空就替换为0
分组查询
将查询结果按照1个或者多个字段进行分组,字段值相同的为一组
GROUP BY 可用于单个字段分组,也可用于多个字段分组
语法:SELECT 列名..., 列函数
`FROM 表名...``WHERE 条件...``GROUP BY 列名...``HAVING 条件...``ORDER BY 列名...`
注意:上面的语法的先后顺序是严格的
SELECT * FROM emp GROUP BY job; #通过job类型进行分组
聚合函数
函数名 | 描述 |
---|---|
SUM(expression) | 求和 |
MAX(expression) | 求最大值 |
MIN(expression) | 求最小值 |
COUNT(expression) | 统计记录函数 |
COUNT(DISITINCT colname) | 统计去重后的记录数 |
AVG(expression) | 求平均值 |
SELECT *,count(*) FROM emp GROUP BY job; # 每个job类型的数量
*SELECT ,MAX(sal) FROM emp GROUP BY deptno; #求每个depno中sal的最大值
*SELECT ,count(DISTINCT job) FROM emp GROUP BY deptno; #求每个deptno中job去重后的数量
GROUP BY + GROUP_CONCAT(expr) 分组统计
**SELECT deptno,count(*),GROUP_CONCAT(ename) `部门员工名单` FROM emp GROUP BY deptno; ** #找出每个部门的员工个数,同时输出每个部门的人的名字
SELECT * AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal)>2000; #使用AVG对分组后的sal求平均值,并使用HAVING增加限定条件进行查询
实例:
SELECT *,count(*) `部门人数`,AVG(sal) `部门平均工资`
FROM emp
WHERE job !='PRESIDENT'
GROUP BY deptno
HAVING `部门平均工资`>1800
ORDER BY `部门平均工资` DESC;-- 计算除了总裁以外,部门的平均薪资,并取部门平均薪资>1800,最后将数据降序排列
LIMIT 2,1 -- 限制最后输出数据,从第2行开始,只输出1行,一般这个函数是在数据比较多的时候去限制输出行数的,同样的可以写作LIMIT 1 OFFSET 1,OFFSET代表跳过几行才进行输出
LIMIT 2,1 #限制最后输出数据,从第2行开始,只输出1行,一般这个函数是在数据比较多的时候去限制输出行数的,同样的可以写作LIMIT 1 OFFSET 1,OFFSET代表跳过几行才进行输出
LIMIT 2 #只显示1条数据
多表查询
笛卡尔积 (交叉连接)
在MySQL中可以为CROSS JOIN 或者省略CROSS即JOIN,或者使用’ ,’
返回结果为被连接的两个数据表的乘积
其实笛卡尔积就是把每一个表1数据都和表2数据做一次组合,把所有组合的可能性都列出来
SELECT emp.*,dept.* FROM emp JOIN dept; #查询表emp和表dept,并将两张表的数据交叉连接
内连接(等值连接)
语法:FROM 表名 [INNER] JOIN 表名 ON 条件 或者 WHERE后面用=
SELECT emp.*,dept.* FROM emp JOIN dept ON emp.deptno=dept.deptno; #增加判定条件emp.deptno=dept.deptno,将交叉后的数据用on(和where效果一样)进行筛选。
内连接(非等值连接)
指的是不用等号连接,而是用>=,<=,>,<,!=,<>等进行连接,主要是为了解决一些比较特殊的结果查询,不常用
外连接
外连接分为左外连接和右外连接,即除了返回符合连接条件的结果之外,还要返回左表(左连接)或者右表(右连接)中不符合连接条件的结果,相对应的使用NULL对应
LEFT OUTER JOIN 左外连接
SELECT c.*,t.* FROM course as c LEFT OUTER JOIN teacher as t ON c.tid=t.id; #完整显示左表,右表只显示完成匹配的。
RIGHT OUTER JOIN 右外连接
SELECT c.*,t.* FROM course as c RIGHT JOIN teacher as t ON c.tid=t.id; #完整显示右表,左表只显示完成匹配的。
**注意:这里LEFT OUTER JOIN和RIGHT OUTER JOIN中间的OUTER是可以省略的,不影响结果**
联合查询
UNION和UNION ALL
UNION:操作符用于合并两个或者多个SELECT语句的结果集
语法:SELECT 字段名 FROM 表名1 UNION[UNION ALL] SELECT 字段名 FROM 表名2;
注意:UNION内部的SELECT语句必须拥有相同数量的列,列不要求数据类型相同,UNION得到的是去重后的结果,UNION ALL得到所有记录,效率高于UNION
SELECT c.*,t.* FROM course as c LEFT JOIN teacher as t ON c.tid=t.id
UNION
SELECT c.*,t.* FROM course as c RIGHT JOIN teacher as t ON c.tid=t.id;
-- 将拼接后的左表和拼接后的右表进行拼接并去重。SELECT c.*,t.* FROM course as c LEFT JOIN teacher as t ON c.tid=t.id
UNION ALL
SELECT c.*,t.* FROM course as c RIGHT JOIN teacher as t ON c.tid=t.id;
-- 将拼接后的左表和拼接后的右表进行拼接。
自连接
自连接:自己和自己连接,虚拟出同一张表,找出两个表中的关联关系
SELECT e1.ename,e1.empno,e1.mgr,e2.empno,e2.ename FROM emp e1 LEFT JOIN emp e2 ON e1.mgr=e2.empno; #将表复制一份,并对所需要的数据进行交叉匹配,然后筛选
子查询
- 子查询:把内层查询结果当作外层查询的参考条件
- WHERE 后面子查询:
WHERE 别名 运算符 (子查询)
- 子查询的列数需要对上,如果查询结果个数大于1,一定要使用IN,如果只有1个值使用=
SELECT * FROM
(SELECT deptno,AVG(sal) as `avg` FROM emp GROUP BY deptno) as a
WHERE a.`AVG`>1500;
-- 将(SELECT deptno,AVG(sal) as `avg` FROM emp GROUP BY deptno)视为子表
利用Python进行数据库操作
pymysql基本操作步骤
db = pymysql.connect(host=‘127.0.0.1’, port=3306,user=‘root’, password=‘123456’, db=‘dc_2019’) #创建数据库连接,host(本机IP地址,本地就是localhost), port(本机端口号),user(用户名), password(密码), db(数据库名称)
import pymysqldb = pymysql.connect(host='localhost',user='root',password='****',port=3306) #使用connect()的方法声明MySQL连接对象db,因在本地启动,host(IP)传入的是localhost,远程启动需要传入公网IP地址。
cursor = db.cursor() #使用cursor()方法获取操作坐标
cursor.execute('SELECT VERSION()') #获取当前版本
cursor.execute('select * from dept;') #括号内直接跟SQL代码,需要以字符串的格式输入
cursor.fetchall() #查看当前获取的结果
db.close() #关闭数据库
db = pymysql.connect(host=‘127.0.0.1’, port=3306,user=‘root’, password=‘123456’, db=‘dc_2019’,cursorclass=pymysql.cursors.DictCursor) #使用cursorclass=pymysql.cursors.DictCursor将获取的数据由元祖嵌套元祖格式改为列表嵌套字典格式
cursor.fetchall()
:拿到所有数据
cursor.fetchone()
:拿到一条数据
cursor.fetchmany()
:拿到指定的多条数据
数据插入
import pymysqldb = pymysql.connect(host='127.0.0.1', port=3306,\
user='root', password='123456', db='dc_2019',cursorclass=pymysql.cursors.DictCursor)cursor = db.cursor()
sql2 = 'INSERT INTO dept(deptno, dname, loc) VALUES(%s, %s, %s)' #创建SQL插入语句
data = [('70', 'Tech2','Xi"an'),('80', 'Tech3', 'Guiyang')] #创建插入的数据
try:cursor.executemany(sql2, data) #执行插入数据操作db.commit() #将插入的数据提交到数据库中
except:db.rollback() #rollback操作,是数据库的一个回滚操作,是为了使数据库中的固化数据和能存数据同步的一个操作
cursor.executemany('select * from dept;') #获取dapt数据表信息
result = cursor.fetchall()print(result)db.close()
sqlalchemy操作数据库
sqlalchemy官方操作手册: https://docs.sqlalchemy.org/en/13/orm/tutorial.html
from sqlalchemy import create_engine db = create_engine("mysql+pymysql://root:123456@localhost:3306/test?harset=utf8") #创建引擎 (数据库+连接工具: //账号:密码@地址:端口号/字符集engine = sqlalchemy.create_engine(string)cur = engine.execute('select * from dept;') # 执行sqlprint(cur.fetchone()) # 返回结果--获取其中一行db.dispose() # 关闭连接
M0ngoDB 储存
https://www.runoob.com/mongodb/mongodb-tutorial.html 菜鸟教程
异步需要使用 motor
import pymongo
client = pymongo.MongoClient() # 连接数据库,默认连接本地的MongoDB
collection = client['stu']['info'] # 打开集合,如果没有这个集合则会自动创建
# 插入单条数据
stu_info = {'_id': 1, 'name': "luoyuchuan", 'age': 30}
conllection.insert_one(stu_info)# 插入多条数据
stu_info_list = [{'_id': 2, 'name': "luoyuchuan1", 'age': 32}, {'_id': 3, 'name': "luoyuchuan2", 'age': 33}]
collention.insert_many(stu_info_list)# 查询数据
results = collection.find()
for item in results:print(item)
Redis 储存
数据结构有 set、str、list等
redis 支持异步
import redis
client = redis.Redis() # 连接redis数据库
result = client.sadd('movie:filter', value) # 保存集合 (key, values)
# 如果已经存在,就会保存失败,则返回为 0 ,保存成功则返回为 1# 清空缓存
client.delete('movie:filter') # 清空指定key的缓存 # 关闭数据库
MD5
import hashlib
md5_hash = hashlib.md5(str(value).encode('utf-8')) # 将 value 进行md5 加密 md5 加密只接收字节格式数据,将其他格式强制转换为字符串,然后进行编码为字节格式
md5_hash = md5_hash.hexdigest() # 计算哈希值,哈希值是惟一的,长度为32位