查询数据库信息
- 查询 MySQL数据库 的版本号
select version(); - 查看当前使用的数据库
select database();
查询表结构
- 查询表结构(desc 是 describe 的缩写)
desc(或describe) 表名;
简单查询
- 查询指定字段的数据( 可以是一个字段,也可以是多个字段,字段之间逗号隔开 )
select 字段1 , 字段2 , 字段3… from 表名; - 查询所有字段
select * from 表名;
as 关键字
这就要提一提这个 as 关键字,如果一个字段名过长,或者不能很好的表达该字段的含义的时候,我们可以使用 as 关键字用来给字段取别名
例:查询字段的同时,给字段取别名(注意只是改变显示结果,表中的不会被改变)
select 字段1 , 字段2 as 字段3 from 表名; (这是字段2被取了别名为字段3,字段1没有变)
其中这个 as 关键字可省略(即只有一个空格)
select 字段1 , 字段2 字段3 from 表名;(与上面的功能一样)
那如果名中有空格怎么办(别名中如果有空格相同处理)?
我们用引号将名字包起来,单引号为使用标准,双引号在部分数据库中不可( MySQL 中可用双引号)
数学表达式
字段可以使用数学表达式( +, - ,* , / 等)
注意:只要参与运算中有 NULL ,则结果一定为 NULL
例:select name , age + 1 from table_1;
条件查询( where )(即查询符合条件的数据)
select 字段1 , 字段2 , from 表名 where 条件;
例:select name , age from table_1 where age >= 18
运算符有:< ,<= ,> ,>= ,and ,or ,<> ,!= ,is null ,in ,not ,like ,= ,between…and…
( <,<=,>,>= ,这四个就不说了,就是你们认为的意思)
- <> (或 !=):不等于
- is null :为 null(is not null 则不为 null )
- in :包含,相当于多个 or ( not in 则不在范围内 )
- not :取非,主要用于 is 和 in 中
- = :等于
- and :且
- or :或
- between…and… :两个值之间,相当于 >= and <=
- like :称为模糊查询,支持 % 和 _ 匹配
% 匹配任意个字符(当然也可以为 0 个字符)
_ 匹配任意一个字符
( 如果查找的字符中有 _ 或 %,可用 \ 转义符号)
运算符之间有优先级,例 and 的优先级要大于 or ,可用 ( ) 来调整执行顺序
排序( order by )
order by 字段名 (默认为升序)
指定降序:order by 字段名 desc;
指定升序:order by 字段名 asc;
按多个字段排序:order by 字段1 升或降 , 字段2 升或降 , … ( 先用字段1排,若相同,则按字段2排 )
也可按照字段的位置排:order by 3 ( 用查询结果的第二列排,但很少这么写,字段的顺序可能会变 )
取部分结果( limit )
将查询的结果集只取一部分,可用于分页查询,也可在部分情况代替分组函数 max ,min
limit 起始下标(从零开始) , 长度
limit 长度
(下面一种默认其实下标为 0 )
去重( distinct )
注意:distinct 只能出现在所有字段的前面,否则会有语法错误,当 distinct 出现在多个字段前面,表示多个字段联合起来去重(如果需要对多个字段中的一个去重,需要之后的知识,暂时不提)
例:
select distinct name , age from table_1; 对
select name , distinct age from table_1; 错
它会把 distinct 当作字段名,age 当作别名,没法正确匹配
函数
函数分为单行处理函数(数据处理函数)和多行处理函数(分组函数)
常见单行处理函数(一个输入对应一个输出)
- lower :转换小写
- upper :转换大写
- substr :取子字符串( substr(被截取的字符串 , 起始下标 , 截取长度 ) )
- length :取长度
- trim :去空格
- str_to_date :将字符串转换为日期
- date_format :格式化日期( 将 date 类型转换为具有一定格式的 varchar 字符串类型)
- format :设置千分位
- round :四舍五入( round(被处理的数字 , 位数(-2 :百位,-1 :十位,0 :个位,1 :一位小数 ,2 :2位小数 …) )
- rand :生成随机数
- ifnull :将 null 转换成一个具体值( ifnull(数据 , 为 null 时被当作的值) )
- concat :字符串拼接
- case…when…then…when…then…else…end :则 数据为…时,则…,为…时,则…,否则…
- timestampdiff :根据单位返回时间差( timestampdiff(单位 , 开始时间 , 结束时间) )
单位可为:year,quarter,month,week,day,hour,minute,second,microsecond
查询结果为 date / datetime 类型时 ( data_format )
data_format 用于 date 转 varchar 类型,通常用于查询
- data_format ( date 类型 , ’ %Y , %m , %d ’ )
- data_format ( date 类型 )
这一种默认转换为 ’ %Y - %m - %d ’
只是在你想让 时间数据 的格式不同的时候使用,不使用一样能查询
datetime 与 date 一样,只不过默认格式不同 ( %Y - %m - %d %H : %i : %s )
常用多行处理函数(多个输入对应一个输出)
- count :计数
- sum :求和
- avg :平均值
- max :最大值
- min :最小值
为什么叫分组函数?
十分重要:因为分组函数在使用之前需要先进行分组,然后才能使用,如果没有对数据进行分组,则默认整张表为一组
分组函数需注意
- 分组函数自动忽略 NULL(不需要提前对 NULL 处理)
- count( 具体字段 )和 count( * ) 不同,count( 具体字段 )表示统计该字段中所有不为 NULL 的数据数量,count( * )表示统计总行数(因为一行记录中不可能都为 NULL ,只要其中有一个数据不为 NULL,则 +1)
- 分组函数不能用在 where 子句中(后面会说原因)
分组查询( group by )
即先进行分组,然后对分好的进行查询
select…from…group by… (group by 在 where 之后执行,在 select 之前执行)
注意:如果有 group by 语句,则 select 后只能跟参加分组的字段,以及分组函数,select 后跟其他字段是没有意义的,甚至在其他数据库中可能报错
如果想要按 每种…的每种… 分类,则 group by … , …
我们可以把这看成将两个字段合成一个字段来看(两个字段联合分组)
过滤分组后的数据( having )
与 where 功能相同,但 having 在 group by 之后执行,where 在 group by 之前执行
having 不能单独使用,必须和group by 搭配使用
关键字顺序 和 执行顺序( 十分十分重要! )
关键字顺序:
- select …
- from …
- where …
- group by …
- having …
- order by…
- limit …
执行顺序
- from …
- where …
- group by …
- having …
- select …
- order by …
- limit …
可以这么理解,我们先 from 选表,然后用 where 筛选,再 group by 分组,再 having 对分好组的数据进行进一步筛选,再 select 查询,再 order by 对查询的数据进行排序,最后 limit 取一部分结果
连接查询( 多张表联合起来查询数据 )
(从一张表单独查询称为单表查询)
分类
连接查询根据表连接的方式可以分为三种:内连接, 外连接,全连接
内连接分为:等值连接, 非等值连接,自连接
外连接分为:左外连接(左连接),右外连接(右连接)
连接方法
表中每一条与其他表的每一条都匹配一次,如果第一个表有 n 个,第二个表有 m 个,则需匹配 n * m 次( 因此尽量降低表连接次数,可以大幅提高效率 )
注意
在连接查询中,我们通常在字段名前都加上了 “表名.” ,这是为了避免混淆,因为有不止一张表连接,并不知道哪个字段在哪张表上,如果不加上,则会在每个表中都找一遍该字段,效率较低。
例:select table_1.name, table_2.sex from table_1 join table_2 on table_1.id = table_2.id
如果表名比较复杂,我们也可以起个别名
例:select t1.name, t2.sex from table_1 t1 join table_2 t2 on t1.id = t2.id
内连接( join 之前有个 inner ,可省略 )
等值连接( 即条件为等量关系)
select … from 表1 join 表2 on … = …
例 :select t1.name, t2.sex from table_1 t1 join table_2 t2 on t1.id = t2.id
非等值连接( 即条件不是等量关系)
select … from 表1 join 表2 on …(不是等量关系就行)
例:select t1.money , t2.age from table_1 t1 join table_2 t2 on t2.age >= t1.min;
自连接(即将一张表看为两张表,自己和自己连接)
例:select t.a , tt.a from table_1 t join table_1 tt on t.b = tt.c
外连接( join 之前有个 outer ,可省略 )
外连接相比于内连接,表之间多了主次关系
右连接( join 之前有个 right ,不可省略 )
表示join关键字右边的表为主表,主要为了将主表的数据全部查出来,捎带关联查询左边的表,即左表只会显示符合搜索条件的记录,而右表的记录将会全部表示出来,左表记录不足的地方均为NULL
左连接( join 之前有个 left ,不可省略 )
与右连接一样,把右改为左即可
全连接( full join )
Oracle数据库支持 full join ,MySQL不支持 full join ,但可以同过 左连接 + union + 右连接 实现
( union 后面会写 )
多张表连接查询
即:select … from a join b on a 和 b 的连接条件 join c on a 和 c 的连接条件…
杂谈
连接查询还可以按照语法的出现时间分类
例 SQL92 :1992年出现的语法, SQL99 :1999年出现的语法
我们上面写的为 SQL99
但是有的文章写的是 SQL92
例:select t1.name, t2.sex from table_1 t1 , table_2 t2 where t1.id = t2.id (SQL92)
其实就是没有 join 与 on,这样并不好,因为表的连接条件和筛选条件都放在where之后,这样语句结构并不清晰
合并查询结果( union /union all )
union :对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
union all :对两个结果集进行并集操作,包括重复行,不进行排序
( 使用union 比较费时,因为要去掉完全相同的重复行 )
例: (select id,name from A ) union all (select id,name from B )
注意:
1.通过 union 进行合并时的列数必须相同
2.不要求合并的表列名称相同,以第一个表的列名为准
3.合并时,列和列的数据类型需要相同,如果不同 MySQL 不会报错,但是 Oracle 会报错
子查询( 即 select 语句嵌套 select 语句 )
子查询可以出现在 select … , where … , from … 后面
出现在 select 中
例:select … , (select …) from … ;
注意:对于 select 后面的子查询,该子查询只能范围一条结果,否则就相当于一条数据匹配了多条数据,会报错
出现在 where 中
可以将子查询结果当作筛选条件
例:我们where中不能出现分组函数,所以我们可以换个思路,利用子查询完成该功能
select name , age from table_1 where age > ( select avg(age) from table_1 )
出现在 from 中
可以将子查询的结果当作一张临时表
例:select … from table_1 join (select …) table_2 on …
注意:这种派生表必须有别名,或者报错
重点
我们要记住重要的一点,select 永远不会进行修改表内数据的操作,只是查询时显示的不同罢了