个人笔记——SQL数据库——查询

SQL数据库——查询

前期准备,建造练习用数据库

-- 创建一个数据库
create database python_test charset=utf8;

-- 使用一个数据库
use python_test;

-- 显示当前使用数据库
select database();

-- 创建学生数据表
create table students(
id int unsigned primary key auto_increment not null,
name varchar(20) default " ", 
age tinyint unsigned default 0,
height decimal(5, 2), 
gender enum("男", "女", "中性", "保密") default "保密", 
cls_id int unsigned default 0, 
is_delete bit default 0
);

-- 创建班级表
create table classes(
id int unsigned auto_increment primary key not null, 
name varchar(30) not null);

-- 准备数据
insert into students values
(0, "小明", 18, 180.00, 2, 1, 0), 
(0, "小月月", 18, 180.00, 2, 2, 1), 
(0, "彭于晏", 29, 185.00, 1, 1, 0), 
(0, "刘德华", 59, 175.00, 1, 2, 1), 
(0, "黄蓉", 38, 160.00, 2, 1, 0), 
(0, "凤姐", 28, 150.00, 4, 2, 1), 
(0, "王祖贤", 18, 172.00, 2, 1, 1), 
(0, "周杰伦", 36, NULL, 1, 1, 0), 
(0, "程坤", 27, 181.00, 1, 2, 0), 
(0, "刘亦菲", 25, 166.00, 2, 2, 0), 
(0, "金星", 33, 162.00, 3, 3, 1), 
(0, "静香", 12, 180.00, 2, 4, 0), 
(0, "郭靖", 12, 170.00, 1, 4, 0), 
(0, "周杰", 34, 176.00, 2, 5, 0);

insert into classes values(0, "python_01期"), (0, "python_02期"), (0, "python_04期");

-- 查看两个表的信息
select * from students;
select * from classes;

-- 除了上篇中提及的可以给字段起别名,也可以给表起别名,通常会在多张表混用的时候用到,如下
select s.name, s.age from students as s;

-- 当有重复语句时可以使用去重,例如查询表中有几种性别,如下
select distinct gender from students;

条件查询

select .... from 表名 where ....

比较运算符

> 大于
select * from students where age >18;
< 小于
select * from students where age <18;
>= 大于等于
<= 小于等于
= 等于
!= 不等于
<> 不等于

逻辑运算符

and
select * from students where age>18 and age<28
or
select * from students where age>18 or height>=180;
not
select * from students where not age<=18 and gender=2;

模糊查询

like

-- %替换1个或多个
-- _ 替换1个
-- 查询姓名中以“小”开头的名字
select name from students where name like "小%";

-- 查询有2个字的名字
select name from students where name like "__" ;

rlike

-- 查询以周开头的姓名
select name from students where name rlike "^周.*$";
-- 查询以周开头 伦结尾的姓名
select name from students where name rlike "^周.*伦$";

范围查询

-- in(1, 3, 8)表示在一个非连续的范围内
-- 查询年龄为18 34的姓名
select name,age from students where age in(18,34,12);

-- between ... and ... 表示在一个连续的范围内
-- 查询年龄不在18到34岁之间的姓名
select name,age from students where age between 18 and 34;

空判断

-- 判空is null
-- 查询身高为空的信息
select * from students where height is null;
-- 判非空is not null

排序

-- order by 字段
-- asc从小到大排序,默认都是从小到大排序,可以省略
-- desc从大到小排序
-- 查询18到34岁之间的男性,按照年龄从小到大排序
select * from students where age between 18 and 34 and gender=1 order by age;

-- 查询年龄在18到34岁之间的女性,身高从高到矮排序
select * from students where (age between 18 and 34) and gender=2 order by height desc;
-- ↑括号可加可不加,加了可以增加可读性
-- 查询年龄在18到34岁之间的女性,身高从高到矮排序,如果身高相同按照年龄从小到大排序,如果年龄也相同,按照id从大到小排序
select * from students where (age between 18 and 34) and gender=2 order by height desc, age asc, id desc;

聚合函数

-- 总数
-- count
-- 查询男性有多少人,女性有多少人
select count(*) as "男性人数" from students where gender=1;
select count(*) as "女性人数" from students where gender=2;

-- 最大值
-- max
-- 查询最大年龄
select max(age) as "最大年龄" from students;

-- 查询女性的最高身高
select max(height) as "女性最高身高" from students where gender=2;

-- 最小值
-- min

-- 求和
-- sum
-- 计算所有人的年龄总和
select sum(age) as "年龄总和" from students;

-- 平均值
-- avg
-- 计算平均年龄
select avg(age) as "平均年龄" from students;
select sum(age)/count(*) from students;

-- 四舍五入 round(123.23, 1) 保留1位小数
-- 计算所有人的平均年龄,保留2位小数
select round(avg(age), 2) as "平均年龄" from students;
-- 计算男性平均身高,保留2为小数
select round(avg(height), 2) as "男性平均身高" from students where gender=1;

分组

-- group by
-- 按照性别分组,查询所有性别
select gender from students group by gender;

-- 计算没中性别当中的人数
select gender,count(*) from students group by gender;

-- 显示不同性别中的姓名
select gender,group_concat(name) from students group by gender;

-- 计算男性的人数
select gender,count(*) from students where gender=1 group by gender;

-- group_concat()
-- 查询同种性别中的姓名
select gender,group_concat(name, "_", age, "_", id) from students where gender=1 group by gender;

-- having
-- 查询平均年龄超过30岁的性别,以及姓名having avg(age) > 30
select gender,group_concat(name),avg(age) from students group by gender having avg(age)>30;

-- 查询每种性别中的人数多于2个的信息
select gender,group_concat(name) from students group by gender having count(*)>2;

分页

limit语句一般放在最后面

-- limit start, count     
-- 限制查询出来
select * from students where gender=1 limit 2;

-- 查询前5个数据
select * from students limit 0, 5;

-- 查询id6-10(包含)的数据
select * from students limit 5, 5;

-- 每页显示2个,第1个页面
select * from students limit 0, 2;
-- 每页显示2个,第2个页面
select * from students limit 2, 2;
-- 每页显示2个,第3个页面
select * from students limit 4, 2;
-- 每页显示2个,第4个页面
select * from students limit 6, 2;  # 规律 —— limit (第N页-1)*每页个数, 每页个数

连接查询

在这里插入图片描述语法:

select * from1 innerleftright join2 on1.=2.
-- inner join ... on
-- 查询有能够对应班级的学生以及班级信息
select * from students inner join classes on students.cls_id = classes.id;

-- 按照要求来显示姓名、班级
select s.name,c.name from students as s inner join classes as c on s.cls_id = c.id;

-- 查询有能够对应班级的学生以及班级信息,显示学生的所有信息,只显示班级名称
select s.name,c.name from students as s inner join classes as c on s.cls_id = c.id;

-- 在以上查询中,将班级姓名显示在第1列,按照班级以及学生id进行排序
select c.name,s.* from students as s inner join classes as c on s.cls_id = c.id order by c.name, s.id;

-- left join
-- 查询每个同学的信息
select * from students as s left join classes as c on s.cls_id=c.id;
-- 一般都使用left join 而不用right join 如有需要可以互换表的位置来达成需求

-- 查询没有对应班级信息的学生
select * from students as s left join classes as c on s.cls_id=c.id having c.id is null;
select * from students as s left join classes as c on s.cls_id=c.id where c.id is null;
-- 以上两条语句等效

自关联

此部分需要《行政区划分sql文件》来进行操作,可以百度搜索下载地址,笔者使用的是2017版
如果遇到的sql文件内部格式如下,则需要将括号内的第一个参数删除

INSERT INTO `areas` VALUES ('3', '110105', '朝阳区', '110100');
-- 需要改成
INSERT INTO `areas` VALUES ('110105', '朝阳区', '110100');

笔者就简单写了一个转换的小脚本,可以参考

import re


def main():
    info_list = []
    with open(r"C:\Users\Administrator\Documents\areas1.sql", 'r', encoding='utf-8') as f:  
    # areas1.sql改成下载的文件名即可,注意修改路径
        file_content = f.readlines()
        c_span = r'\((.*)\)'
        for line in file_content:
            in_list = re.findall(c_span, line)[0].split(',')
            reform_line = r"INSERT INTO `areas` VALUES " + "(%s,%s,%s)" % (in_list[1], in_list[2], in_list[3]) + ";"
            info_list.append(reform_line)
            # print(reform_line)

    with open(r"C:\Users\Administrator\Documents\areas.sql", 'w', encoding='utf-8') as f:
        for lines in info_list:
            f.write(lines)


if __name__ == '__main__':
    main()
  • 创建areas表
create table areas(id int primary key, 
atitle varchar(20), 
p_id int);
  • 将sql文件导入areas
! 退出mysql
! 进入sql文件所在的路径,然后登陆mysql,并使用原来的数据库
source areas.sql;

-- 查看省份
select * from areas where p_id is null;

-- 显示山东省的所有市
select Province.atitle as "省",City.atitle as "市" from areas as Province inner join areas as City on City.p_id=Province.id having Province.atitle="山东省";

子查询

-- 标量子查询
-- 查询出高于平均身高的信息

-- 查询最高的男声信息
select * from students where height = (select max(height) from students where gender=1);

-- 改写上面的自关联查询省市
select * from areas where p_id = (select id from areas where atitle="山东省");
-- 子查询的效率没有自关联高
发布了33 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_38354769/article/details/98877014