数据过滤
- != 和 <> 作用相同
- BETWEEN操作符:where id BETWEEN 1001 AND 1009;
- AND优先级比OR高,多条件并列时最好用圆括号控制
- IN操作符: where id IN (1002, 1003);
- NOT操作符:支持对IN、BETWEEN、和EXISTS取反
- LIKE操作符:
- where name LIKE ‘张%’; # 以“张”开头
- where name LIKE ‘%张%’; # 包含“张”字符
- where name LIKE ‘张%强’; # 以‘“张”开头,以“强”结尾
数据汇总(聚集)
AVG() 函数
select AVG(price) as avg_price from products where id=’1001’;
avg_price 是别名,搜索时AVG函数会忽略值为NULL的行,如果想获得多个列的平均值就要用多个AVG函数。用此函数的时候可能会用到group by先分组,同时用到having来过滤。
还有COUNT() 、SUM() 、 MAX() 、MIN() ,规则类似。
注意不能用 max(sum(score))
的复合形式,如果想找总和中的最大者,可以用 sum(score)>all(...select语句...)
数据排序
ORDER BY 列1名 ASC, 列2名 DESC LIMIT m, n;
列1名 ASC, 列2名 DESC
:先按列1升序,再按列2降序。LIMIT m,n
:从第m+1开始的n条数据
数据分组
HAVING :实现的是对分组的过滤,一般与聚集函数连用;WHERE是对行的过滤,与聚集函数无关
GROUP BY :分组去重。group by候面不能跟where,where后面能跟group by
DISTINCT:分组去重。如果有多个NULL,仅保留一个。
二者效率:
- 有索引的情况下:效率差不多。
- 无索引的情况下:distinct效率更高。原因是二者都会进行分组操作,但group by可能会进行排序,触发filesort,导致执行效率低。
易用性:
- distinct关键字会对后面跟的所有字段生效;
- group by更灵活,能利用having等聚集函数对分组进行过滤。
子查询
把一条select语句返回的结果用于另一条select语句的where子句
联结表
select name, age, score |
上面的语句查了三列数据,前两列属于student表,第三列属于exam表。这种需求需要在where语句中把两个表联结起来,用的就是等值联结,它基于两个表做相等测试。这也叫做内部联结,等价于下面的写法:
select name, age, score |
在使用这种语法时,联结条件用特定的on子句而不再用where,但传递的条件是一致的。
如果不进行联结,返回的结果就是笛卡儿积,检索出的行数等于两表行数的乘积,其中很多条数据都是数据库中不存在的。
关于内联结和外联结:
内连接分为等值连接和自然连接:
- 等值连接:取两者笛卡尔积中属性值相等的元组
- 自然连接是一种特殊的等值连接。它要求去除重复列。
外连接分为左连接、右连接和全连接:
- 左连接:查询A表中所有数据以及B表中符合联结条件的数据
- 右连接:查询B表中所有数据以及A表中符合联结条件的数据
- 全连接:返回左右表的所有行。哪个表中没有的就用null填充。(MySQL不支持全外连接,所以只能采取关键字UNION来联合左、右连接)
建表语句
create table student( |
auto_increment告诉MySQL,本列每当增加一行时自动增量。每个表只允许一个auto_increment列,而且它必须被索引(如,通过使它成为主键),可使用select last_insert_id()
获取刚刚自增的值。
当然,在insert的时候可以手动指定一个值,只要它是唯一的(至今尚未被使用过)即可,该值将被用来替代自动生成的值,且后续将基于该手动插入的值继续增长。
插入语句
insert into 表名 (列1名,列2名,列3名) values(列1数据,列2数据,列3数据), (列1数据,列2数据,列3数据) |
其中列名是可以省略书写的,后面单个的value中就不用写对应的数据。
可省略的列名:可为空的列、具有default值的列、自动递增的列
也可以直接不写整个列名列表,直接写values,那么每个value中的数据个数要严格等于数据表的列数(包括上面提到的三种特殊的列)。