SQL-DQL
DQL概述
DQL(Data Query Language):即数据查询语言,查询是数据库中使用频率最高的一个操作,可以从一个表中查询数据,也可以从多个表中查询数据。
关键字:select
基础语法
select 查询列表 form 表名;
特点:
1.查询列表可以是:表中的字段,常量,表达式,函数
2.查询的结果是一个虚拟的表格,查询中的操作不改变表格的原数据
本篇文章查询的基础表如下,建表和修改表的操作位于如下链接SQL之结构定义语言DDL(数据库的操作+数据库表的概述及操作), SQL之数据操纵语言DML(数据的增,删,改)
查询结果处理
1、查询常量值
select 常量 form 表名;
2、查询表达式
select 表达式 from 表名;
例如 select 100*98;
3、查询函数
select 函数 from 表名;
函数: 类似于java中的方法,将一组逻辑语句事先在数据库中定义好,可以直接调用
好处:
(1) 隐藏了实现细节;
(2) 提高的代码的重用性.
调用:
select 函数名(实参列表) [from 表名]
大家可以看到,我从t_stu表中查询了版本号,获得了7条数据,而这7条数据并没有在我的表中存在,只是以我表中的格式出现了,这是大家需要注意的地方.
4、特定列查询
select 列1,列2,列3... from 表名;#最常用
5、全部列查询
select * from 表名;# *代表全部
6、排除重复列
select distinct 列1,列2,列3... from 表名;
7、算数运算符
“+”"-""*""/":这里的运算符只能做算数运算,没有其他的任何功能,且操作只表现在查询,不改变原数据.
SELECT stu_grade-10 FROM t_stu;
SELECT stu_grade+1000 FROM t_stu;
SELECT stu_grade*10 FROM t_stu;
SELECT stu_grade/10 FROM t_stu;
函数查询
单行函数
字符函数
1、length():获取参数值的字节个数;
SELECT LENGTH(stu_grade) FROM t_stu;
2、char_length():获取参数值的字符个数;
SELECT CHAR_LENGTH(stu_name) FROM t_stu;
3、concat(str1,str2…):拼接字符串;
SELECT CONCAT(stu_name,':',stu_grade)AS person_grade FROM t_stu;
AS是为这个新拼接的查询列重命名
4、upper()/lower():将字符串变成大写/小写;
SELECT LOWER(stu_name) FROM t_stu;
5、substring(str,起始位置,长度):截取字符串,位置从1开始;
SELECT SUBSTRING(stu_birth,1,4)AS stu_year FROM t_stu;
6、instr(str,指定字符串):返回子串第一次出现的索引,如果找不到返回0;
SELECT INSTR(stu_name,'T') FROM t_stu;
7、lpad/rpad(str,length,填充字符):用指定的字符实现左/右填充将str填充为指定长度;
SELECT LPAD(stu_name,7,'棒') FROM t_stu;
SELECT RPAD(stu_name,7,'棒') FROM t_stu;
8、replace(str,old,new):替换所有的子串;
SELECT REPLACE(stu_sex,'女','nv') FROM t_stu;
9、trim(str):去掉字符串前后的空格或子串,trim(指定子串 from 字符串);
SELECT LENGTH(TRIM(stu_id)) FROM t_stu;
10、trim(指定子串 from 字符串):去掉字符串的指定前后子串。
SELECT LENGTH(TRIM('a' FROM 'asssssa')) FROM t_stu;
逻辑处理
1、case when 条件 then 结果1 else 结果2 end;可以有多个when
SELECT stu_name,
(CASE WHEN stu_status=1 THEN '已注册' ELSE '未注册' END) AS stu_status
FROM t_stu;
2、ifnull(被检测值,默认值)函数检测是否为null,为null返回指定值,否则返回原值。
SELECT stu_name,
IFNULL(stu_grade,'未录入成绩')AS grade
FROM t_stu;
3、if函数:if else的效果
if(条件,结果1,结果2)#慢足条件出结果1,否则出结果2
SELECT stu_name,
IF(stu_grade=98.9,'成绩一致',stu_grade)AS grade
FROM t_stu;
数学函数
1、round(数值):四舍五入;
SELECT ROUND(stu_grade)AS grade FROM t_stu;
2、ceil(数值):向上取整,返回>=该参数的最小整数;
SELECT CEIL(stu_grade)AS grade FROM t_stu;
3、floor(数值):向下取整,返回<=该参数的最大整数;
SELECT FLOOR(stu_grade)AS grade FROM t_stu;
4、truncate(数值,保留的小数位数):截断,小数点后截断几位;
SELECT TRUNCATE(stu_grade,0)AS grade FROM t_stu;
5、mod(被除数,除数):取余,被除数为正,则为正,被除数为负,则为负;
SELECT MOD(stu_grade,10)AS grade FROM t_stu;
6、rand():获取随机数,返回0-1之间的小数。
SELECT stu_name,
(stu_grade+RAND())AS rand_grade
FROM t_stu;
日期函数
1、now():返回当前系统日期+时间;
SELECT NOW() FROM t_stu;
2、curdate():返回当前系统日期,不包含时间;
SELECT CURDATE() FROM t_stu;
3、curtime():返回当前系统时间,不包含日期;
SELECT CURTIME() FROM t_stu;
4、获取日期的指定部分,year()、month()、day()、hour()、minute()、second()
SELECT YEAR(stu_now),
MONTH(stu_now),
DAY(stu_now),
HOUR(stu_now),
MINUTE(stu_now),
SECOND(stu_now)
FROM t_stu;
5、str_to_date():将指定日期格式的字符串转换为日期格式。
SELECT STR_TO_DATE('2021年1月15','%Y年%m月%d日') FROM t_stu;
6、date_format():将日期转为字符串。
SELECT DATE_FORMAT(stu_now,'%Y年%m月%d日') FROM t_stu;
7、datediff(date1,date2):返回两个日期相差的天数,date1-date2
SELECT DATEDIFF(stu_now,STR_TO_DATE(stu_birth,'%Y-%m-%d')) FROM t_stu;
符号 | 含义 |
---|---|
%Y | 年,4位 |
%m | 月,数值00-12 |
%d | 日,数值00-31 |
%H | 小时,数值00-23 |
%i | 分钟,数值00-59 |
%s | 秒,数值00-59 |
%f | 微秒 |
%T | 时间,24小时(hh:mm:ss) |
%j | 年的天,数值001-366 |
%w | 周的天,数值0=星期天-6=星期六 |
聚合函数
功能: 用作统计使用, 又称为聚合函数或统计函数或组函数.
1.sum() : 求和
SELECT SUM(stu_grade),SUM(stu_birth) FROM t_stu;
2.avg() : 求平均值
SELECT AVG(stu_grade) FROM t_stu;
3.max() : 求最大值
SELECT MAX(stu_name) FROM t_stu;
4.min() : 求最小值
SELECT MIN(stu_age) FROM t_stu;
5.count() : 计数, 数据统计,统计有多少行数据,不算null
SELECT COUNT(stu_name),COUNT(stu_sex),COUNT(stu_ph) FROM t_stu;
注意:
(1)sum,avg一般用于处理数值型
(2)max,min,count可以处理任意类型
(3)以上聚合函数都会忽略null值
(4)count函数的单独使用一般会用count(*)统计所有行数
(5)和分组函数一起查询的字段要求是group by后面的字段
eg:统计男女生人数
SELECT COUNT(stu_id),stu_sex FROM t_stu GROUP BY stu_sex;
条件查询
用法: 使用where子句,将不满足条件的行全部过滤,where子句紧随from子句.
语法:select 结果 from 表名 where 条件;
1.比较运算符
= , !=或<> , > , < , >= , <=
2.逻辑运算
and 与
or 或
not 非
/*
使用where子句,将不满足的条件筛掉,where子句紧随from子句
*/
SELECT stu_name FROM t_stu WHERE stu_sex = '男' ;
SELECT * FROM t_stu WHERE stu_sex = '女';
SELECT * FROM t_stu WHERE stu_grade>99;
SELECT * FROM t_stu WHERE stu_grade<99;
SELECT * FROM t_stu WHERE stu_grade>99 AND stu_grade<=100;
3.模糊查询
关键字like : 是否匹配与一个模式, 一般和通配符搭配使用,可以判断字符型数值或数值.
通配符: % 任意多个字符, 包含0个字符 _ 任意单个字符
between and 两者之间, 包含临界值;
in(a,b):判断某字段的值是否属于in列表中的某一项
注意: 判断数据是否为空使用 is null 或者 is not null
#模糊查询
SELECT stu_name FROM t_stu WHERE stu_name LIKE('苏%');
SELECT * FROM t_stu WHERE stu_name LIKE '%居%';
SELECT * FROM t_stu WHERE stu_name LIKE '%白';
#between and
SELECT * FROM t_stu WHERE stu_grade BETWEEN 99 AND 100;
#in()
SELECT * FROM t_stu WHERE stu_age IN(20,600);
SELECT * FROM t_stu WHERE stu_age NOT IN(20,600);
#判断为null
SELECT * FROM t_stu WHERE stu_ph IS NULL;
UNION操作符
1.union操作符用于连接两个以上的select语句的结果组合到一个结果集合中,要求两个查询列数相同
2.语法
#语法1
[sql 语句1]
union
[sql 语句2]
#语法2
[sql 语句1]
union all
[sql 语句2]
注意:
1.union all是直接连接, 取到的是所有值, 记录可能有重复, 记录可能有重复, union是取唯一值, 记录没有重复.
2.效率: union和union all关键字都是将两个结果集合并为一个, 但这两者从使用和效率上来说都有所不同.
(1)对重复结果的处理: union在进行表连接后筛掉重复的记录,union all不会去除重复记录
(2)对排序的处理: union将会按照字段的顺序进行排序; union all只是简单的将两个结果合并后就返回;
(3)从效率来说, union all要比union快很多, 所以, 如果可以确认的两个结果中不包含重复数据且不需要排序的话,南无就是用union all
SELECT stu_id,stu_name,stu_age,stu_grade FROM t_stu WHERE stu_age>600
UNION ALL
SELECT stu_id,stu_name,stu_age,stu_grade FROM t_stu WHERE stu_age<20;
排序
1.查询结果排序, 使用order by子句排序, 对原表数据无影响;
2.order by排序列, asc/desc, asc代表升序, desc代表的是降序, 默认为升序;
3.order by子句中可以支持单个字段, 多个字段, 表达式, 函数, 别名.
4.使用
/*
语法
order by 排序列 ASC/DESC
asc代表的是升序,desc代表的是降序
默认是升序
*/
SELECT
(stu_grade+RAND())AS rand_grade -- 结果
FROM
t_stu -- 表名
WHERE stu_grade IS NOT NULL -- where筛选条件,有where条件先执行where条件,对筛选后的结果进行排序
ORDER BY rand_grade DESC; -- order by子句 desc降序 asc升序
数量限制
limit子句: 对查询的显示结果限制数目(sql语句最末尾的位置)
数据库的行数选择是从0开始的, 与字符函数中的substring()截取的起始位置不同,一定要区分
作用: 对查询的结果有数目限制
应用: 分页查询
语法:
/*
语法1
select 结果 from 表名 limit 查询数量;
*/
SELECT
* -- 结果
FROM
t_stu -- 表名
WHERE stu_age IS NOT NULL
ORDER BY stu_age DESC
LIMIT 4; -- 从第一行数据开始的查询数量
/*
语法2
select 结果 from 表名 limit 开始行数,查询数量;
*/
SELECT
* -- 结果
FROM
t_stu -- 表名
WHERE stu_age IS NOT NULL
ORDER BY stu_age DESC
LIMIT 2,3; -- 从排序后的第三行数据开始查询三条
/*
语法3
select 结果 from 表名 limit 查询数量 offset 跳过的数据行数;
*/
SELECT
* -- 结果
FROM
t_stu -- 表名
WHERE stu_age IS NOT NULL
ORDER BY stu_age DESC
LIMIT 3 OFFSET 2; -- offset指的是跳过2行数据,开始查询3行数据
分组查询
语法
select 分组函数,列(要求出现在group by的后面)
from 表名
[where 筛选条件]
group by 分组的列表
[having 分组后的筛选]
[order by子句]
[limit 子句 限制数量]
简单的就是
select 结果 from 表名 group by 分组列
-- 统计男生女生各有多少人
SELECT stu_sex,COUNT(*) FROM t_stu GROUP BY stu_sex;
-- 统计男生女生中的最高成绩
SELECT stu_sex,MAX(stu_grade) FROM t_stu GROUP BY stu_sex;
注意: 查询列表比较特殊, 要求是分组函数和group by后出现字段
分组查询中的筛选条件分为两类:
数据源 | 源位置 | 关键字 | |
---|---|---|---|
分组前筛选 | 原始表 | group by子句的前面 | where |
分组后筛选 | 分组后的结果集 | group by的后面 | having |
-- 查询性别人数大于2的是哪个性别,对分组后的结果进行条件的筛选
SELECT stu_sex,COUNT(*)AS c
FROM t_stu
WHERE stu_grade > 0 -- 在分组前对数据进行筛选过滤
GROUP BY stu_sex
HAVING c>2 -- 分组后对条件进行筛选过滤
ORDER BY c DESC;
子查询
1.含义: 出现在其它语句( insert,update,delete,select )中的select语句,称为子查询或内查询; 外部的查询语句,称为主查询或外查询
-- 在insert 语句中使用子查询,不能为要添加的数据字段加唯一索引
INSERT INTO t_stu(stu_name,stu_sex,stu_grade,stu_age)
SELECT stu_name,stu_sex,stu_grade,stu_age
FROM t_stu
WHERE stu_id = 5;
-- 在update 语句中使用子查询 注意查询的结果不能在本张表中查询
#先创建一张新表
CREATE TABLE stu_temp(
stu_id SMALLINT,
stu_name VARCHAR(10),
stu_sex CHAR(1) DEFAULT'男'
)
UPDATE t_stu
SET stu_name='王五'
WHERE stu_name = (
SELECT stu_name
FROM stu_temp
WHERE stu_id = 1
)
-- 在delete 语句中使用子查询 准备查询的结果不能在本张表中查询
DELETE
FROM t_stu
WHERE stu_id = (
SELECT stu_id
FROM stu_temp
WHERE stu_name = '王五'
)
2.按功能,结果集的行列数不同分为:
(1)标量子查询: 结果集只有一行一列;
(2)列子查询: 结果集只有一列多行;
(3)行子查询: 结果集有一行多列;
(4)表子查询: 结果集为多行多列
3.注意:
(1)select语句后面: 仅仅支持标量子查询;
(2)from后面: 仅仅支持表子查询;
(3)where或having后面:支持标量子查询,列子查询,行子查询(较少);
(4)exists后面(相关子查询):支持表子查询.
-- 在select语句后面加子查询,只能是标量子查询
SELECT stu_name,(SELECT NOW()),stu_id
FROM t_stu;
-- from后面:支持表子查询 查询性别大于4的是哪个性别
SELECT * FROM
(SELECT stu_sex,COUNT(*)c FROM t_stu GROUP BY stu_sex)t -- 把查询结果当成一张表
WHERE t.c>4;
-- 列子查询 查询年龄大于100的所有信息
SELECT *
FROM t_stu
WHERE stu_age IN(
SELECT stu_age
FROM t_stu
WHERE stu_age > 100
)
-- 行子查询
#查询学号最大,成绩最高的学生,需要同时满足
SELECT *
FROM t_stu
WHERE (stu_id,stu_grade) = (
SELECT MAX(stu_id),MAX(stu_grade)
FROM t_stu
)