SELECT语法
SELECT基本语法
SELECT 的语法格式为:
SELECT {* | <filed1>, ..., <filedN>}
FROM <table 1>, … , <tableN>
WHERE <expression>
GROUP BY <filed> HAVING <expression>
ORDER BY <filed>
LIMIT [<offset>,] <row count>
语法说明:
<table>:指定被操作的表名。
<field>:星号(*)查询表的所有字段列表,表示所要查询字段的名称。
WHERE <expression>:是可选项,如果选择该项,将限定查询数据必须满足该查询条件
GROUP BY < filed>: 该子句告诉 MySQL 如何显示查询出来的数据,并按照指定的字段分组
ORDER BY< filed >: 该子句告诉 MySQL 按什么样的顺序显示查询出来的数据,可以进行的排序有升序(ASC)和降序(DESC),默认情况下是升序
LIMIT[<offset>,]<row count>:该子句告诉 MySQL 每次显示查询出来的数据条数
设置别名
为表设置别名:
<表名> [AS] <别名>
select id, name, age, gender from employee as emp;
语法说明:
<表名>:数据库中存储的数据表的名称
<别名>:查询时指定的表的新名称
AS关键字可以省略,省略后需要将表名和别名用空格隔开
为字段设置别名:
<字段名> [AS] <别名>
select emp.id, name '姓名', age AS '年龄', gender '性别' from employee as emp;
语法说明:
<字段名>:为数据表中字段定义的名称
<字段别名>:字段新的名称
AS关键字可以省略,省略后需要将字段名和别名用空格隔开
条件查询
WHERE关键字的语法格式:
WHERE <expression>
语法说明:
<expression>可以是:
带比较运算符和逻辑运算符的查询条件
带 BETWEEN AND 关键字的查询条件
带 IS NULL 关键字的查询条件
带 IN 关键字的查询条件
带 LIKE 关键字的查询条件
...
MySql支持4中运算符:
- 算数运算符
执行算数运算,如加、减、乘、除等 -
比较运算符
主要用于数值的比较、字符串匹配等,包括大于、小于、等于、... -
逻辑运算符
逻辑判断,返回值为布尔型,包括与、或、非等 -
位运算符
位运算符是在二进制数上进行计算的运算符。位运算会先将操作数变成二进制数,进行位运算。然后再将计算结果从二进制数变回十进制数。包括按位与、按位或、取反、左移、右移等
分组查询
GROUP BY关键字的语法格式:
GROUP BY <field>
语法说明:
<field>:表示需要分组的字段名称,多个字段时用逗号隔开
GROUP BY单独使用
SELECT age FROM employee GROUP BY age;
GROUP BY与GROUP_CONCAT()函数搭配使用
SELECT age, GROUP_CONCAT(name) FROM employee GROUP BY age;
GROUP BY与聚合函数搭配使用,如 COUNT(),SUM(),AVG(),MAX() 和 MIN()等
SELECT age, COUNT(id) FROM employee GROUP BY age;
WITH ROLLUP:在group分组字段的基础上再进行统计数据
SELECT age, count(id) FROM employee GROUP BY age WITH ROLLUP;
过滤分组
HAVING 关键字的语法格式:
HAVING <查询条件>
HAVING 关键字和 WHERE 关键字都可以用来过滤数据,且 HAVING 支持 WHERE 关键字中所有的操作符和语法。
WHERE 和 HAVING 关键字也存在以下几点差异:
一般情况下,WHERE 用于过滤数据行,而 HAVING 用于过滤分组
WHERE 查询条件中不可以使用聚合函数,而 HAVING 查询条件中可以使用聚合函数
WHERE 在数据分组前进行过滤,而 HAVING 在数据分组后进行过滤
WHERE 根据数据表中的字段进行过滤,而 HAVING 是根据前面已经查询出的字段进行过滤
WHERE 查询条件中不可以使用字段别名,而 HAVING 查询条件中可以使用字段别名
mysql> select * from employee having age > 30;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 3 | 13101010002 | 李四 | 女 | 45 | NULL | 销售顾问 | 0 |
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
+----+-------------+------+--------+-----+--------+----------+---------+
5 rows in set
mysql> select id, mobile,name
from employee having age > 30;
1054 - Unknown column 'age' in 'having clause'
对查询结果排序
ORDER BY关键字的语法格式:
ORDER BY <field> [ASC|DESC]
语法说明:
<field>:表示需要排序的字段名称,多个字段时用逗号隔开
ASC|DESC:ASC表示字段按升序排序;DESC表示字段按降序排序。其中ASC为默认值
注意:
ORDER BY 关键字后可以跟子查询
当排序的字段中存在空值时,ORDER BY 会将该空值作为最小值来对待
ORDER BY 指定多个字段进行排序时,MySQL 会按照字段的顺序从左到右依次进行排序
单字段排序
select * from employee order by age desc;
多字段排序
select * from employee order by age , mobile desc;
注意:在对多个字段进行排序时,排序的第一个字段必须有相同的值,才会对第二个字段进行排序
mysql> select * from employee order by age desc;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
| 3 | 13101010002 | 李四 | 女 | 45 | NULL | 销售顾问 | 0 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 1 | 13101010001 | 张三 | 男 | 24 | 市场部 | 市场总监 | 8888.88 |
+----+-------------+------+--------+-----+--------+----------+---------+
6 rows in set
mysql> select * from employee order by age , mobile desc;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 1 | 13101010001 | 张三 | 男 | 24 | 市场部 | 市场总监 | 8888.88 |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 3 | 13101010002 | 李四 | 女 | 45 | NULL | 销售顾问 | 0 |
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
+----+-------------+------+--------+-----+--------+----------+---------+
6 rows in set
mysql> select * from employee order by mobile desc, age desc ;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
| 3 | 13101010002 | 李四 | 女 | 45 | NULL | 销售顾问 | 0 |
| 1 | 13101010001 | 张三 | 男 | 24 | 市场部 | 市场总监 | 8888.88 |
+----+-------------+------+--------+-----+--------+----------+---------+
6 rows in set
限制查询结果的条数
LIMIT关键字的语法格式:
LIMIT [<offset>,] <row count>
语法说明:
<offset>:表示从哪行记录开始显示,可省略,默认为0
<row count>: 表示显示记录的条数
注意:LIMIT 后的两个参数必须都是正整数
指定初始位置
select * from employee limit 2,4;
select * from employee limit 4 offset 2;
不指定初始位置
select * from employee limit 3;
mysql> select * from employee limit 3;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 1 | 13101010001 | 张三 | 男 | 24 | 市场部 | 市场总监 | 8888.88 |
| 3 | 13101010002 | 李四 | 女 | 45 | NULL | 销售顾问 | 0 |
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
+----+-------------+------+--------+-----+--------+----------+---------+
3 rows in set
mysql> select * from employee limit 2,4;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
+----+-------------+------+--------+-----+--------+----------+---------+
4 rows in set
mysql> select * from employee limit 4 offset 2;
+----+-------------+------+--------+-----+--------+----------+---------+
| id | mobile | name | gender | age | dept | post | salary |
+----+-------------+------+--------+-----+--------+----------+---------+
| 4 | 13101010003 | 王二 | 女 | 50 | 销售部 | 销售总监 | 8888.88 |
| 5 | 14101010004 | 麻子 | 男 | 36 | NULL | 总经理 | NULL |
| 6 | 14101010005 | TOM | 未知 | 36 | 销售部 | 销售顾问 | 6055.22 |
| 7 | 14101010006 | JACK | 男 | 50 | NULL | NULL | 2222.01 |
+----+-------------+------+--------+-----+--------+----------+---------+
4 rows in set
对查询结果去重
DISTINCT关键字的语法格式:
SELECT DISTINCT <field> FROM <table>;
语法说明:
<field>:为需要消除重复记录的字段名称,多个字段时用逗号隔开
注意:
DISTINCT 关键字只能在 SELECT 语句中使用
在对一个或多个字段去重时,DISTINCT 关键字必须在所有字段的最前面
如果 DISTINCT 关键字后有多个字段,则会对多个字段进行组合去重
子查询
子查询在 WHERE 中的语法格式:
WHERE <表达式> <操作符> (子查询)
语法说明:
<操作符>: 可以是比较运算符和 IN、NOT IN、EXISTS、NOT EXISTS 等关键字
IN | NOT IN
IN: 当表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返回 FALSE
SELECT * from emp e where e.dept_id IN (SELECT id from dept where `name` = '市场部');
SELECT * from emp e where e.dept_id NOT IN (SELECT id from dept where `name` = '市场部');
EXISTS | NOT EXISTS
EXISTS: 用于判断子查询的结果集是否为空,若子查询的结果集不为空,返回 TRUE,否则返回 FALSE
SELECT * from emp e where EXISTS (SELECT id from dept where `name` = '市场部' and dept.id = e.dept_id);
SELECT * from emp e where NOT EXISTS (SELECT id from dept where `name` = '市场部' and dept.id = e.dept_id);
SELECT (子查询) FROM 表名
SELECT id, `name` , dept_id, (SELECT name from dept where dept.id = emp.dept_id) 'dept_name' from emp;
SELECT * FROM (子查询) AS 表的别名
select emp_id, emp_name from (SELECT e.id emp_id, e.`name` emp_name, e.age from emp e) tmp;
交叉连接(CROSS JOIN)
交叉连接的语法格式:
SELECT <field> FROM <table1> CROSS JOIN <table2> [WHERE <expression>]
或 SELECT <field> FROM <table1>, <table2> [WHERE <expression>]
语法说明:
<field>: 需要查询的字段名称,多个字段时用逗号隔开
<table1>, <table2>:需要交叉连接的表名
WHERE <expression>:用来设置交叉连接的查询条件
SELECT * FROM emp CROSS JOIN dept WHERE emp.dept_id = dept.id;
SELECT * FROM emp, dept WHERE emp.dept_id = dept.id;
内连接(INNER JOIN)
内连接的语法格式:
SELECT <field> FROM <table1> INNER JOIN <table2> [ON子句]
语法说明:
<field>: 需要查询的字段名称,多个字段时用逗号隔开
<table1>, <table2>:需要内连接的表名
INNER JOIN :内连接中可以省略 INNER 关键字,只用关键字 JOIN
ON 子句:用来设置内连接的连接条件
WHERE <expression>:用来设置交叉连接的查询条件
SELECT emp.id, emp.`name`, emp.gender, dept.`name` dept_name, role.`name` role_name from emp
JOIN dept on emp.dept_id = dept.id
JOIN emp_role_ref erf on erf.emp_id = emp.id
JOIN role on role.id = erf.role_id;
外连接(OUTER JOIN)
左连接的语法格式:
SELECT <field> FROM <table1> LEFT OUTER JOIN <table2> [ON子句]
语法说明:
LEFT OUTER JOIN :左连接中可以省略 OUTER 关键字,只使用关键字 LEFT JOIN
<table1><table2>:需要左连接的表名,”table1”为基表,“table2”为参考表。左连接查询时,可以查询出“table1”中的所有记录和“table2”中匹配连接条件的记录。如果“table1”的某行在“table2”中没有匹配行,那么在返回结果中,“table2”的字段值均为空值(NULL)
右连接的语法格式:
SELECT <field> FROM <table1> RIGHT OUTER JOIN <table2> [ON子句]
语法说明:
RIGHT OUTER JOIN :右连接中可以省略 OUTER 关键字,只使用关键字RIGHT JOIN
<table1><table2>:需要左连接的表名,”table2”为基表,“table1”为参考表。左连接查询时,可以查询出“table2”中的所有记录和“table1”中匹配连接条件的记录。如果“table2”的某行在“table1”中没有匹配行,那么在返回结果中,“table1”的字段值均为空值(NULL)
mysql> SELECT emp.id, emp.`name`, emp.gender, dept.`name` dept_name from emp
LEFT JOIN dept on emp.dept_id = dept.id
ORDER BY emp.id LIMIT 10;
+----+--------+--------+-----------+
| id | name | gender | dept_name |
+----+--------+--------+-----------+
| 1 | 张三01 | 男 | NULL |
| 2 | 张三02 | 女 | NULL |
| 3 | 张三03 | 男 | 客户部 |
| 4 | 张三04 | 男 | 销售部 |
| 5 | 张三05 | 男 | 服务部 |
| 6 | 张三06 | 未知 | 市场部 |
| 7 | 张三07 | 女 | 服务部 |
| 8 | 张三08 | 男 | 市场部 |
| 9 | 张三09 | 男 | 客户部 |
| 10 | 张三10 | 女 | 客户部 |
+----+--------+--------+-----------+
10 rows in set
mysql> SELECT emp.id, emp.`name`, emp.gender, dept.`name` dept_name from dept
RIGHT JOIN emp on emp.dept_id = dept.id
ORDER BY emp.id LIMIT 10;
+----+--------+--------+-----------+
| id | name | gender | dept_name |
+----+--------+--------+-----------+
| 1 | 张三01 | 男 | NULL |
| 2 | 张三02 | 女 | NULL |
| 3 | 张三03 | 男 | 客户部 |
| 4 | 张三04 | 男 | 销售部 |
| 5 | 张三05 | 男 | 服务部 |
| 6 | 张三06 | 未知 | 市场部 |
| 7 | 张三07 | 女 | 服务部 |
| 8 | 张三08 | 男 | 市场部 |
| 9 | 张三09 | 男 | 客户部 |
| 10 | 张三10 | 女 | 客户部 |
+----+--------+--------+-----------+
10 rows in set