查询数据库信息

  1. 查询 MySQL数据库 的版本号
    select version();
  2. 查看当前使用的数据库
    select database();

查询表结构

  1. 查询表结构(desc 是 describe 的缩写)
    desc(或describe) 表名;

简单查询

  1. 查询指定字段的数据( 可以是一个字段,也可以是多个字段,字段之间逗号隔开 )
    select 字段1 , 字段2 , 字段3… from 表名;
  2. 查询所有字段
    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…
( <,<=,>,>= ,这四个就不说了,就是你们认为的意思)

  1. <> (或 !=):不等于
  2. is null :为 null(is not null 则不为 null )
  3. in :包含,相当于多个 or ( not in 则不在范围内 )
  4. not :取非,主要用于 is 和 in 中
  5. = :等于
  6. and :且
  7. or :或
  8. between…and… :两个值之间,相当于 >= and <=
  9. 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 当作别名,没法正确匹配

函数

函数分为单行处理函数(数据处理函数)和多行处理函数(分组函数)

常见单行处理函数(一个输入对应一个输出)

  1. lower :转换小写
  2. upper :转换大写
  3. substr :取子字符串( substr(被截取的字符串 , 起始下标 , 截取长度 ) )
  4. length :取长度
  5. trim :去空格
  6. str_to_date :将字符串转换为日期
  7. date_format :格式化日期( 将 date 类型转换为具有一定格式的 varchar 字符串类型)
  8. format :设置千分位
  9. round :四舍五入( round(被处理的数字 , 位数(-2 :百位,-1 :十位,0 :个位,1 :一位小数 ,2 :2位小数 …) )
  10. rand :生成随机数
  11. ifnull :将 null 转换成一个具体值( ifnull(数据 , 为 null 时被当作的值) )
  12. concat :字符串拼接
  13. case…when…then…when…then…else…end :则 数据为…时,则…,为…时,则…,否则…
  14. timestampdiff :根据单位返回时间差( timestampdiff(单位 , 开始时间 , 结束时间) )
    单位可为:year,quarter,month,week,day,hour,minute,second,microsecond

查询结果为 date / datetime 类型时 ( data_format )

data_format 用于 date 转 varchar 类型,通常用于查询

  1. data_format ( date 类型 , ’ %Y , %m , %d ’ )
  2. data_format ( date 类型 )
    这一种默认转换为 ’ %Y - %m - %d ’

只是在你想让 时间数据 的格式不同的时候使用,不使用一样能查询

datetime 与 date 一样,只不过默认格式不同 ( %Y - %m - %d %H : %i : %s )

常用多行处理函数(多个输入对应一个输出)

  1. count :计数
  2. sum :求和
  3. avg :平均值
  4. max :最大值
  5. min :最小值

为什么叫分组函数?

十分重要:因为分组函数在使用之前需要先进行分组,然后才能使用,如果没有对数据进行分组,则默认整张表为一组

分组函数需注意

  1. 分组函数自动忽略 NULL(不需要提前对 NULL 处理)
  2. count( 具体字段 )和 count( * ) 不同,count( 具体字段 )表示统计该字段中所有不为 NULL 的数据数量,count( * )表示统计总行数(因为一行记录中不可能都为 NULL ,只要其中有一个数据不为 NULL,则 +1)
  3. 分组函数不能用在 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 搭配使用

关键字顺序 和 执行顺序( 十分十分重要! )

关键字顺序:

  1. select …
  2. from …
  3. where …
  4. group by …
  5. having …
  6. order by…
  7. limit …

执行顺序

  1. from …
  2. where …
  3. group by …
  4. having …
  5. select …
  6. order by …
  7. 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 永远不会进行修改表内数据的操作,只是查询时显示的不同罢了