SQL查询基础
1、单表查询
从数据库中查找数据 专业的称谓又称为投影
基本查询语句结构
select 列 from 表
* 所有列不是所有其他东西
查询所有数据
例:SELECT * FROM t_studen
需要执行比较细的操作 加上条件筛选:查询id为2号的学生信息
SELECT * FROM t_student WHERE id=2;
筛选的执行步骤
例:SELECT * FROM t_student WHERE id=2;
SELECT * (3) 再查询 筛选完后 我最终投影的结果就是筛选后的结果,不是每行都显示出来,显示行的数据是筛选后的数据 所以最后执行 select
FROM t_student (1) 把整张表加到内存里面 把整张表找到后加到内存里面
WHERE id =2 (2) 筛选 因为一张表里面的数据需要去做一个筛选,不想让每行都显示,这样就没意义了,所以要进行一个条件筛选
只投影某些列
SELECT id,s_name FROM t_student; 只投影结果,而不是改变表数据,很多人会迷惑,其他列会不会不见了
查询出来显示成中文,比如s_name显示成学生姓名
AS 加上别名 (列的别名)
SELECT id,s_name AS "学生姓名" FROM t_student;
表别名,当有几张表的时候,表的名字很长,会给表加上别名
SELECT t_student.s_name FROM t_student -- 但是在一张表中这样写t_student.s_name 没有任何意义
SELECT a.s_name FROM t_student a 本次查询 a就代表t_student 就可以a.s_name
1.1、筛选掉重复数据 DISTINCT
SELECT DISTINCT s_name FROM t_student;
SELECT DISTINCT s_name,s_classid FROM t_student; distinct 要重复列(s_name,s_classid)的数据完全一样
1.2、选择操作:写筛选条件的方法:
并且 and 也可以写成&&
SELECT * FROM t_student WHERE id=2 AND s_name=‘李四‘ AND s_classid=‘二班‘
SELECT * FROM t_student WHERE id=2 AND s_name=‘李四‘ && s_classid=‘二班‘
或者 or 也可以写成 ||
SELECT * FROM t_student WHERE s_classid=‘二班‘ OR id=1
SELECT * FROM t_student WHERE s_classid=‘二班‘ || id=1
范围操作BETWEEN……AND……(包含)
语法:select 列 from 表名 where 列名 between 值 and 值;
SELECT * FROM t_student WHERE age>=18 AND age<=25
SELECT * FROM t_student WHERE age BETWEEN 18 AND 25 -- 等同于上面大于等于 及小于等于
小于等于18和一班,大于等于25和一班
SELECT * FROM t_student WHERE age<=18 OR age>=25 AND s_classid=‘一班‘;
这条语句执行出来的结果是小于等于18的所有数据和大于等于25并且是一班的数据
是因为and的优先级高于or的优先级
所以应该这样写:
SELECT * FROM t_student WHERE (age<=18 OR age>=25 ) AND s_classid=‘一班‘;
小于等于18和一班,大于等于25和一班 and优先级高于or 所以一般是单独用括号括起来
查询学生年纪为18 或者25 或者28
SELECT * FROM t_student WHERE age=18 OR age=25 OR age=28
in 操作
简化上面的那种情况 where 列 in(值1,值2,值3)
SELECT * FROM t_student WHERE age IN(18,25,30)
not in 操作
值不是25的
SELECT * FROM t_student WHERE age NOT IN(25)
返回限定行数 limit
limit 数字=从第一行数据开始 数两行
limit 数字n,数字m 从第n行数据开始(跟数组下标计算方式一样) 数m行 跟字符串substr类似
SELECT * FROM t_student LIMIT 2
SELECT * FROM t_student LIMIT 2,2
返回第二行之后所有行 第二个参数足够大 超出也只会返回到最后一行为止
SELECT * FROM t_student LIMIT 2,100
返回多少行 应用场景? 一些网站数据较多时,要出现分页
1.3、模糊查询
% 不限制字符
语法:select * from 表名 where 字段 like ‘x%’;
找所有姓张的学生
SELECT * FROM t_student WHERE s_name=‘张三‘ = 全匹配 不会帮你自动模糊查询
SELECT * FROM t_student WHERE s_name LIKE ‘张%‘ like % 不限制字符(0-N个字符)的模糊查询
SELECT * FROM t_student WHERE s_name LIKE ‘%张%‘ like % 可以查到包含张 如 *张*
SELECT * FROM t_student WHERE s_name LIKE ‘%张 like % 可以查到张,以张结尾, 但是不能是张**
占位符 _(下划线) 一个下划线代表一个字符
找所有姓张的学生,并且名字长度为三个字
SELECT * FROM t_student WHERE s_name LIKE ‘张__‘ like _ 限制字符数的模糊查询 一个下划线代表一个字符
查询年纪为空的学生信息
SELECT * FROM t_student WHERE age="" ‘‘”代表为空白的值
空值 is null
SELECT * FROM t_student WHERE age IS NULL 代表空值 没有输入数据
不是空 is not null
SELECT * FROM t_student WHERE age IS NOT NULL
上面的操作 投影出来的东西 跟我们的表数据(输入顺序)中是一样的顺序,比如想让它以
排序 order by 升序 ASC 降序 desc
年龄大小排序
SELECT * FROM t_student ORDER BY age -- 默认是升序
SELECT * FROM t_student ORDER BY age DESC -- 降序
SELECT * FROM t_student ORDER BY age ASC -- 升序
多于一个条件的排序
SELECT * FROM t_student ORDER BY age ASC,id ASC 会先让age排序,
然后如果age有两个一样,再让id排序age的顺序,一般不会全部考虑,只有当两条数据一样,才考虑第二个条件
1.4、聚合函数
计数 count(列)
语法:select count(列) as ‘总数’ from 表名 where 条件 -------一般在计数的时候都会给取个别名
Count 统计时不包含没有值的项
计算年龄在20岁的人数
例:SELECT COUNT(*) FROM t_student WHERE age=20
求和 sum(列)
语法:select sum(列) from 表名
例:SELECT SUM(age) FROM t_student
平均 avg
语法:(1)select sun(列)/count(*) from 表名
例:SELECT SUM(age)/COUNT(*) FROM t_student
(2)select avg(列) from 表名 -------默认不包含空
例:SELECT AVG(age) FROM t_student
(3)Select avg(ifnull(列,0)) from 表名 -----如果是空数据,补成0在求平均
例:SELECT AVG(IFNULL(age,0)) FROM t_student
最大值、最小值
语法:select max(列),min(列) from 表名
例:SELECT MAX(age),MIN(age) FROM t_student
分组 group by
语法:select 列名 ,count(*) from 表名 group by 需要分组的列名 (必须和前面的列相关联)
select 列名 ,count(*) from 表名 group by 需要分组的列名 having 条件
例:查询每一班的人数
SELECT s_classid,COUNT(*) FROM t_student GROUP BY s_classid;
显示10岁(where)的人数大于2的班级的一条数据
SELECT s_classid,COUNT(*) FROM t_student WHERE age=10 GROUP BY s_classid HAVING(COUNT(*)>2);
执行步骤:
SELECT s_classid,COUNT(*) -- 4 投影
FROM t_student -- 1 把表加载到内存
WHERE age=10 -- 2 筛选
GROUP BY s_classid -- 3分组
HAVING(COUNT(*)>2) -- 5 二次筛选,首先要得到第一次的结果 才可以进行筛选
-- having跟where都是筛选条件,where是分组前,因为分组前没有执行聚合函数
-- having是在分组后,只能用做聚合函数的过滤
显示10岁(where)的人数大于1的班级并且按照人数排序
SELECT s_classid,COUNT(*) FROM t_student WHERE age=10 GROUP BY s_classid HAVING(COUNT(*)>=1) ORDER BY COUNT(*) limit 1
执行步骤:
SELECT s_classid,COUNT(*) -- 4 投影
FROM t_student -- 1 把表加载到内存
WHERE age=10 -- 2 筛选
GROUP BY s_classid -- 3 分组
HAVING(COUNT(*)>=1) -- 5 二次筛选 首先要得到第一次的结果 才可以进行筛选
ORDER BY COUNT(*) DESC -- 6 二次分组
LIMIT 1 -- 7 限定行数 肯定是你执行完之后最终的结果的 行数
-- 这7步顺序千万不能搞错
2、多表查询
2.1、相关子查询
子查询必须依赖于主查询 ,子查询单独运行会报错,依赖于主查询的结果
select嵌套 只能返回单行单列
每次主查询 执行一次,子查询也会执行一次,最终执行N+1次,效率低下,如果主查询没有提供数据,子查询无法执行
语法:select 列名1,列名2,(select 列名 from 表名 where 条件) from 表名
例:SELECT s_name,(SELECT c_name FROM t_class WHERE c_id=s_classid) FROM t_student
2.2 非相关子查询
from 嵌套 必须要给嵌套的子查询表起别名,可返回多行多列数据
子查询对主查询没有依赖 子查询只会执行一次,只会在from的时候才执行,性能较高,能独立运行,只是给主查询提供条件值
语法:select 列名1 ,列名2,.... from (select 列名 from 表名 [where 条件] ) [where 条件]
例:查询性别为女 并且姓名为张三的
SELECT * FROM (SELECT * FROM t_student WHERE s_sex=‘女‘) AS t1
WHERE t1.s_name=‘张三‘;
where 嵌套 执行2次,子查询可以单独运行,不依赖主查询,只是给主查询提供条件值
语法:select 列名1,列名2, .... from 表名 where 列名 关系运算符 (select 列明 from 表名 where 条件)
例:查询一班的学生有哪些
SELECT * FROM t_student WHERE s_classid=(SELECT c_id FROM t_class WHERE c_name=‘一班‘)
in 多条值
例:查询一班的学生有哪些
语法:select 列名1,列名2,.... from 表名 where 列名 in (select 列明 from 表名 where 条件)
SELECT * FROM t_student WHERE s_classid in (SELECT c_id FROM t_class WHERE c_name=‘一班‘)
any 和all 必须跟子查询 不能单独使用
all 任意值
语法:select 列名1,列名2, .... from 表名 where 列名 关系运算符 all (select 列明 from 表名 where 条件)
例:查询分数高于任意一个张三的所有学生 -- 使用all
SELECT * FROM t_student WHERE s_score>ALL(SELECT s_score FROM t_student WHERE s_name=‘张三‘)
any
语法:select 列名1,列名2, .... from 表名 where 列名 关系运算符 any (select 列明 from 表名 where 条件)
例:查询分数高于任意一个张三的所有学生
SELECT * FROM t_student WHERE s_score>ANY( SELECT s_score FROM t_student WHERE s_name=‘张三‘);
还可以使用MIN
SELECT * FROM t_student WHERE s_score>(SELECT MIN(s_score) FROM t_student WHERE s_name=‘张三‘);
子查询不管怎么变,都只有三种,在where中嵌套一个,form 一个,select一个