(二)MySQL基本语句
0 Views with
本文字数:2,682 字 | 阅读时长 ≈ 12 min

(二)MySQL基本语句

0 Views with
本文字数:2,682 字 | 阅读时长 ≈ 12 min

查询数据

基本查询语句

select 
    {* | <字段列表>}
    {
      form <表1>,<表2>...
      [where <表达式>]
      [group by <grop by definition>]
      [having <exception> [{<option> <expression>}...]]
      [order by <order by definition>]
      [limit [<offset>,] <row count>]
    }

select [字段1,字段2...] from [表或视图] where [查询条件];

解释:

  * {* | <字段列表>}  : 表示查询的字段,多个字段间用逗号隔开
  * group by<字段>    : 告诉MySQL如何显示查询出来的数据,并按照指定的字段分组
  * [order by<字段>]  : 告诉MySQL按什么样的顺序显示查询出来的数据,如:升序(ASC)、降序(DESC)
  * [limit [<offset>] <row count>] :  告诉MySQL每次显示查询出来的数据条数

单表查询

带IN关键字的查询

select id from tb_emp_2 where id in(2,3) order by id asc

带BETWEEN AND的范围查询

select id from tb_emp_2 where id between 2 and 4

带LIKE的字符匹配查询

通配符是一种在SQL的WHERE条件子句中拥有特殊意思的字符,SQL语句中支持多种通配符,可以和LIKE一起使用的通配符有'%'和'_'

‘%’通配符,匹配任意长度的字符,甚至包括零字符

查找’t‘字母开头的员工姓名:
select id,name from tb_emp_2 where name like 't%';

查找包含’t‘的员工姓名:
select id,name from tb_emp_2 where name like '%t%';

查询以’t‘开头,并以’g‘结尾的员工姓名:
select id,name from tb_emp_2 where name like 't%g';

‘_’通配符,一次只能匹配任意一个字符

查询以’e‘结尾,并且前面包含四个字符的员工姓名:
select id,name from tb_emp_2 where name like '____e';

IS NULL 查询空值

select id,name from tb_emp_2 where name is null;

带AND的多条件查询

MySQL在WHERE子句中使用AND操作符限定只有满足所有查询条件的记录才会被返回,可以用AND连接多个条件,多个条件见用AND分开

例如:查询名字中包含't'并且年龄等于18岁的员工
    select id,name,age from tb_emp_2 where name like '%t%' and age = 18;

带OR的多条件查询

在WHERE声明中使用OR操作符,表示只需要满足其中一个条件的记录即可返回。OR可以用来连接多个查询条件。

例如:查询姓名中包含’t‘或'o'且年龄等于18的员工
      select id,name,age from tb_emp_2 where name like '%t%' or '%o%' and age = 18;

注意: and的优先级高于OR

DISTINCT查询结果不重复

如,查询表中所有name不重复的数据:
select id,distinct name from tb_emp_2;

ORDER BY 对查询结果排序

1. 单列排序(默认按字母顺序排列)
select name from tb_emp_2 order by name;

2. 多列排序(哪个字段在前先依照哪个排序)
select age,name from tb_emp_2 order by age,name;

3. 指定排序方向
select name,age from tb_emp_2 order by age desc,name asc;
**注意:MySQL排序的时候默认按照asc升序排序,且第二个字段仅仅是在第一个字段的基础上排序
**如下列情况:
  mysql> select age,name from tb_emp_2 order by age,name asc;
  +------+--------+
  | age  | name   |
  +------+--------+
  | 12   | tu     |
  | 13   | apple  |
  | 18   | orange |
  +------+--------+
  mysql> select age,name from tb_emp_2 order by age,name desc;
  +------+--------+
  | age  | name   |
  +------+--------+
  | 12   | tu     |
  | 13   | apple  |
  | 18   | orange |
  +------+--------+
  mysql> select age,name from tb_emp_2 order by age desc,name desc;
  +------+--------+
  | age  | name   |
  +------+--------+
  | 18   | orange |
  | 13   | apple  |
  | 12   | tu     |
  +------+--------+

  前两个结果一样,因为都只是给name字段后加了条件,而不加条件的age字段则默认按圣墟排列,所以无论name字段后加什么排序结果都是一样的。
  想要多多列都进行降序排列,要在每个字段后都加desc  

GROUP BY 分组查询

语法:[group by 字段] [having <条件表达式>]

创建分组

例如:按照password排序,并记录其相同值的数量
  select password count(*) from tb_emp_2 group by password;

例如:查看这些分组的password分别对应哪些name
  select password,group_concat(name) from tb_emp_2 group by password;

使用HAVING过滤分组

group by可以和having一起限定表中的数据进行分组,只有满足条件的分组才能被显示出来。
如:按id排序,并查询名字中包含't'的客户
select id,name from tb_emp_2 group by id having name like '%t%';

where和having的区别:
having 是在数据分组之后进行过滤来选择分组的,而where是在分组之前用来选择记录的。另外where排除的记录不再包含在分组中

在GROUP BY子句中使用WITH ROLLUP

使用WITH ROLLUP关键字,在所有查询出来的分组记录之后增加一条记录,在记录计算查询出的所有记录的总和,即统计记录数量
例如:
mysql> select f_id,count(*) as total from tb_fruits group by f_id;
+------+-------+
| f_id | total |
+------+-------+
|    1 |     1 |
|    2 |     2 |
|    3 |     2 |
|    4 |     1 |
+------+-------+
mysql> select f_id,count(*) as total from tb_fruits group by f_id with rollup;
+------+-------+
| f_id | total |
+------+-------+
|    1 |     1 |
|    2 |     2 |
|    3 |     2 |
|    4 |     1 |
| NULL |     6 |
+------+-------+

多字段分组

使用group by 进行多字段分组:
如:
mysql> select f_id,f_name from tb_fruits group by f_id,f_name;
+------+--------+
| f_id | f_name |
+------+--------+
|    1 | apple  |
|    2 | banana |
|    2 | orange |
|    3 | apple  |
|    3 | banana |
|    4 | grape  |
+------+--------+

但是:
mysql> select * from tb_fruits group by f_id,f_name;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db_1.tb_fruits.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

所以:
使用group by 进行多字段分组,要注意你分组的字段在select后指定,

原因:
SQL的GROUP By的语法:
  SELECT 选取分组中的列+聚合函数 from 表名称 GROUP BY 分组的列
  所以是先有分组,再有检索的列,检索的列只能在分组中的列中选

综上:
  就是:GROUP BY后的字段是先确定的,而SELECT后的字段是从GROUP BY分组中选的。
  即:GROUP BY后面有的字段,SELECT后面才允许有;反之没有的SELECT也不能有

mysql> select f_id,f_name from tb_fruits group by f_id;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db_1.tb_fruits.f_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
mysql> select f_id from tb_fruits group by f_id,f_name;
+------+
| f_id |
+------+
|    1 |
|    2 |
|    2 |
|    3 |
|    3 |
|    4 |
+------+
mysql> select f_id,f_name from tb_fruits group by f_id,f_name;
+------+--------+
| f_id | f_name |
+------+--------+
|    1 | apple  |
|    2 | banana |
|    2 | orange |
|    3 | apple  |
|    3 | banana |
|    4 | grape  |
+------+--------+

使用LIMIT限制查询结果的数量

LIMIT返回指定序列行的数据

语法:
  LIMIT [位置偏移量,] 行数
解释:
  [位置偏移量]:可选参数,不写,默认会从表的第一条记录开始(第一条记录的偏移量是0,第二条是1...)
  行数:指示从第[位置偏移量开始],共显示多少行记录

例如:
mysql> select * from tb_fruits limit 4,2;
+----+------+--------+---------+
| id | f_id | f_name | f_price |
+----+------+--------+---------+
|  5 |    3 | apple  | 1.02    |
|  6 |    4 | grape  | 2.10    |
+----+------+--------+---------+

使用聚合函数查询

avg()     返回某列的平均值
count()   返回某列的行数
max()     返回某列的最大值
min()     返回某列的最小值
sum()     返回某列值的和

1. count()函数
  注意:
      count(*) 计算表中总的行数,不管某列有数值或为空值
      count(字段名) 计算指定列下的总行数,计算是将会忽略空值的行

连接查询

INNER JOIN内连接查询

INNER JOIN使用比较运算符进行表间某些列数据的比较操作
举例:
mysql> select tb_vegetables.f_id,v_name,v_price,f_name,f_price from tb_fruits inner join tb_vegetables on tb_vegetables.f_id = tb_fruits.f_id;
+------+----------+---------+--------+---------+
| f_id | v_name   | v_price | f_name | f_price |
+------+----------+---------+--------+---------+
|    1 | tomato   | 1.02    | apple  | 1.02    |
|    2 | cucumber | 1.00    | orange | 1.5     |
|    2 | cucumber | 1.00    | banana | 1.8     |
|    4 | beans    | 1.00    | grape  | 2.10    |
+------+----------+---------+--------+---------+

mysql> select tb_vegetables.f_id,v_name,v_price,f_name,f_price from tb_fruits,tb_vegetables where tb_vegetables.f_id = tb_fruits.f_id;
+------+----------+---------+--------+---------+
| f_id | v_name   | v_price | f_name | f_price |
+------+----------+---------+--------+---------+
|    1 | tomato   | 1.02    | apple  | 1.02    |
|    2 | cucumber | 1.00    | orange | 1.5     |
|    2 | cucumber | 1.00    | banana | 1.8     |
|    4 | beans    | 1.00    | grape  | 2.10    |
+------+----------+---------+--------+---------+
分析:
  f_id是tb_vegetables和tb_fruits两张表中共有的字段
  因为f_id是共有的字段,也是作为内连接的条件,那么遵循`表名.字段名`格式

外连接查询

外连接查询将查询多个表中相关联的行;内连接时,返回查询结果集合中仅是符合查询条件和连接条件的才行

LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。
RIGHT JOIN(右连接):返回包括左表中的所有记录和左表中连接字段相等的记录。

LEFT JOIN(左连接)

左连接的结果包含LEFT OUTER子句中指定的左表中的所有行,而不仅仅是连接列所匹配的行

mysql> select * from tb_orders;
+-------+---------------------+------+
| o_num | o_date              | f_id |
+-------+---------------------+------+
|     1 | 2018-01-01 00:00:00 |    1 |
|     2 | 2018-01-01 00:00:00 |    2 |
|     3 | 2018-01-01 00:00:00 |    4 |
|     4 | 2018-01-01 00:00:00 |    5 |
+-------+---------------------+------+
mysql> select * from tb_fruits;
+----+------+---------+---------+
| id | f_id | f_name  | f_price |
+----+------+---------+---------+
|  1 |    1 | apple   | 1.02    |
|  2 |    2 | orange  | 1.5     |
|  3 |    3 | banana  | 1.8     |
|  4 |    2 | banana  | 1.8     |
|  5 |    3 | apple   | 1.02    |
|  6 |    4 | grape   | 2.10    |
|  7 |    5 | beans_h | 1.0     |
+----+------+---------+---------+

mysql> select tb_fruits.f_id,tb_orders.o_num from tb_fruits left outer join tb_orders on tb_fruits.f_id = tb_orders.f_id;
+------+-------+
| f_id | o_num |
+------+-------+
|    1 |     1 |
|    2 |     2 |
|    2 |     2 |
|    4 |     3 |
|    5 |     4 |
|    3 |  NULL |
|    3 |  NULL |
+------+-------+

根据左连接的定义:左表(tb_fruits)中的所有行都会展示,若右表中没有匹配的行,数据就显示为null

RIGHT JOIN(右连接)

右连接是左连接的反向连接,将返回右表中的所有行。若右表的某行在左表中没有匹配的行,左表返回空值

mysql> select tb_fruits.f_name,tb_orders.o_num from tb_fruits right outer join tb_orders on tb_fruits.f_id = tb_orders.f_id;
+---------+-------+
| f_name  | o_num |
+---------+-------+
| apple   |     1 |
| orange  |     2 |
| banana  |     2 |
| grape   |     3 |
| beans_h |     4 |
| NULL    |     5 |
+---------+-------+

##子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询。在SELECT子句中先计算子查询,子查询的结果作为外层另一个查询的过滤条件,查询可以基于一张或多张表。
子查询中常用的操作符有:ANY(SOME)、ALL、IN、EXISTS、子查询可以嵌套在SELECT、UPDATE、DELETE语句中

1. 带ANY、SOME的子查询:
  select num1 from tb_1 where num1 > any(select num2 from tb_2);
  表示如果tb_2中的num2和tb_1中的num1比较,只要大于num2列的任意一个值即可满足

2. 带ALL的子查询
  select num1 from tb_1 where num1 > all(select num2 from tb_2);
  需要num1大于num2列的所有值才满足条件

3. 带EXISTS的子查询
  select * from tb_fruits where exists(select o_num from tb_orders where o_num = 3);
  只要tb_orders中存在o_num = 3的数据,子查询就返回true,那么就会进行外层的查询

4. 带IN关键字的查询
  select 

插入语句

INSERT INTO table_name (column_list) VALUES(value_list)

更新语句

UPDATE table_name SET column_name = value WHERE (condition)

删除语句

DELETE FROM table_name [WHERE <condition>]


交流

如果大家有兴趣,欢迎大家加入我的Java交流群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

如果你觉得这篇文章帮助到了你,你可以帮作者买一杯果汁表示鼓励