ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 数据操作 - 查询 SELECT 大概是 SQL 语言中最常用的语句,而且怎样使用它也最为讲究;用它来选择记录可能相当复杂,可能会涉及许多表中列之间的比较。本节介绍 SELECT 语句关于查询的最基本功能。 语法如下: SELECT column_list // 选择哪些列 FROM table_list // 从何处选择行 WHERE primary_constraint // 行必须满足什么条件 GROUP BY grouping_columns // 怎样对结果分组 HAVING secondary_constraint // 行必须满足的第二条件 ORDER BY sorting_columns // 怎样对结果排序 LIMIT count // 结果限定 上述语法中除了 SELECT 关键字之外,其他每样东西都是可选的。有些数据库需要用 FROM 关键字,但是 MySQL 允许对表达式求值而不引用任何表。 **注意:** 所有使用的关键词必须精确地以上面的顺序给出。例如,一个 HAVING 子句必须跟在 GROUP BY 子句之后和 ORDER BY 子句之前。 ### 查询所有数据 SELECT * FROM employee; // 查所有数据 SELECT employee_name,job_title FROM employee; // 查特定列 使用星号(*)一些注意事项说明: - 它会返回所有列数据,但是可能部分列数据我们并不使用,MySQL 数据库服务器和应用程序之间就会产生不必要的磁盘 I/O 和网络流量。 - 如果明确指定列,结果集更可预测,更易于管理。试想一下,当有其他开发人员修改表结构并添加更多的列,查询返回的结果集可能与您期望的就不一样了。 - 可能会暴露敏感信息给未经授权的用户。 ### 条件查询 SELECT * FROM employee WHERE office_id = 1000; // 单个条件查询 SELECT * FROM employee WHERE office_id = 1000 AND gender = '男'; // 多条件 且关系 查询 SELECT * FROM employee WHERE office_id = 1000 OR office_id = 1001; // 多条件 或关系 查询 SELECT * FROM employee WHERE report_to IS NULL; // NULL 判断 SELECT * FROM employee WHERE report_to IS NOT NULL; // NOT NULL 判断 SELECT * FROM employee WHERE office_id IN (1000,1001); // 范围查询 SELECT * FROM employee WHERE office_id NOT IN (1000,1001); // 范围查询 SELECT * FROM employee WHERE office_id >= 1000 AND office_id <= 1005; // 范围查询 SELECT * FROM employee WHERE office_id BETWEEN 1001 AND 1005; // 范围查询 SELECT * FROM employee WHERE office_id NOT BETWEEN 1001 AND 1005; // 范围查询 ### 模糊查询 SELECT * FROM employee WHERE employee_name LIKE '%吴'; // %通配符代表任意多个字符 SELECT * FROM employee WHERE employee_name LIKE '%吴%'; SELECT * FROM employee WHERE employee_name LIKE '吴_'; // _通配符代表任意一个字符 ### 查询排序 SELECT * FROM employee ORDER BY office_id ASC; // 按照升序排列 SELECT * FROM employee ORDER BY office_id DESC // 按照降序排列 SELECT * FROM employee ORDER BY office_id, dept_id; // 按照两列进行排序,前面的为主要的 #### 分页查询 SELECT * FROM employee LIMIT 5; // 获取前5条数据 SELECT * FROM employee LIMIT 0,5; // 获取前5条数据 SELECT * FROM employee LIMIT 5,5; // 获取第5-10条数据 SELECT * FROM employee LIMIT 5 OFFSET 5; // 获取第5-10条数据 ### 去重查询 SELECT DISTINCT status FROM `order`; // 查询有那些订单状态 ### 统计函数(聚合函数) SELECT COUNT(*) FROM `order`; // 查询表中有多少条数据 SELECT MAX(total_money) FROM `order`; // 取支付的最大值 SELECT MIN(total_money) FROM `order`; // 取支付的最小值 SELECT SUM(total_money) FROM `order`; // 取支付的总和 SELECT AVG(total_money) FROM `order`; // 取支付的平均值 **注意:** 如果表名或字段名是 MySQL 的保留字,需要用波浪号包裹起来,否则会引发错误。所以对表名以及字段命名请尽量避免 MySQL 保留字。 参考链接:[MySQL保留字](https://dev.mysql.com/doc/refman/5.7/en/keywords.html) ### 分组查询 SELECT status FROM `order` GROUP BY status; // 查询有那些订单状态 SELECT status, COUNT(*) AS total FROM `order` GROUP BY status; // 查询各类状态的订单有多少 SELECT status, COUNT(*) AS total FROM `order` GROUP BY status HAVING total > 50; 查询各类状态的订单量, 要求订单量大于50 **注意:** HAVING 子句筛选条件针对每一个分组的行,而 WHERE 子句的过滤条件是针对每个单独的行。 ### 连接查询 **内连接(INNER JOIN)** MySQL 的 INNER JOIN 子句的语法如下: SELECT column_list FROM t1 INNER JOIN t2 ON join_condition1 INNER JOIN t3 ON join_condition2 ... 当我们使用 INNER JOIN 子句将 T1 表连接 T2 表: 在 T1 表的每一行与 T2 表中的每一行进行比较,检查是否它们都满足连接条件。当连接条件匹配,它将返回在 T1 和 T2 表合并选择列的行记录。 如果没有找到匹配,查询将返回一个空的结果集。 下面的思维图说明了 INNER JOIN 子句是如何工作的。结果集中的行必须出现在:T1 和 T2 两个表中。 ![内连接原理图](http://www.studymysql.com/uploads/images/161007/07141053_99799.png) 从 product 表中读取产品代码(product_code)和产品名称(product_name)从 category 表中读取分类名称(name) - product 表中的每个产品都属于 category 表中的一个分类; - category 表中每个分类在 product 表中有 零个或多个产品; - category 和 product 是一对多的关系; ``` SELECT p.product_code, p.product_name, c.name AS category_name FROM product AS p INNER JOIN category AS c ON p.category_id = c.category_id LIMIT 10; ``` **左连接(LEFT JOIN)** SELECT column_list FROM t1 LEFT JOIN t2 ON join_condition1 LEFT JOIN t3 ON join_condition2 ... 当我们使用 LEFT JOIN 子句将 T1 表连接 T2 表: 如果左表 T1 中的一行基于连接条件与右表 T2 一行相匹配,此行将被包括在结果集中。如果左表中的行不能匹配右表中的行,则左边的表中的行也被选择,并与右表中的一个“伪造”的行合并。这个”伪造”的行 用 NULL 值填充。 下面的思维图说明了 LEFT JOIN 子句是如何工作的。两个圆之间的交集表示那些符合两个表中的行记录,左圆的其余部分表示 T1 表没有与 T2 表相匹配的记录。左表中的所有行都会被包括在结果集中。 ![左连接原理图](http://www.studymysql.com/uploads/images/161007/07211054_93390.png) 查找每个客户自己的所有订单: - order 表中的每一个订单必须属于 customer 表中的某一客户; - customer 表中每个客户在 order 表中有零个或多个订单; - customer 和 order 是一对多的关系; ``` SELECT cs.customer_id, cs.customer_name, o.order_number, o.status FROM `customer` AS cs LEFT JOIN `order` AS o ON cs.customer_id = o.customer_id ORDER BY o.order_number ASC LIMIT 10; ``` **右连接(RIGHT JOIN)** 右连接是相对于左连接,和左连接原理类似。把主表和连接表互换,也即是左连接和右链接互换。 ``` SELECT cs.customer_id, cs.customer_name, o.order_number, o.status FROM `order` AS o RIGHT JOIN `customer` AS cs ON o.customer_id = cs.customer_id ORDER BY o.order_number ASC LIMIT 10; ``` **全连接(FULL JOIN)** 只要其中某个表存在匹配,FULL JOIN 关键字就会返回行。 ``` SELECT cs.customer_id, cs.customer_name, o.order_number, o.status FROM `order` AS o FULL JOIN `customer` AS cs ON o.customer_id = cs.customer_id ORDER BY o.order_number ASC LIMIT 10; ``` **自连接(SELF JOIN)** 自连接是一个比较 “特殊” 的连接方式,它自己连接自已本身。 当我们想在同一个表中行记录上结合多列,可以考虑使用自连接。要执行自连接操作,必须要使用表的别名,以帮助 MySQL 从同一个表名称中区分左表和右表。 查找雇员以及雇员的直属领导: 在 employee 表中,我们不仅存储员工的数据,还有组织结构的数据。*report_to* 字段是用来存储这个雇员的管理者的ID。 为了获得整个组织结构,我们可以在 *employee_id* 和 *report_to* 这两个字段上连接 employee 表本身。 ``` SELECT e.office_id, e.employee_name AS '雇员姓名', m.employee_name AS '直属领导' FROM employee AS e LEFT JOIN employee AS m ON m.employee_id = e.report_to ORDER BY e.office_id, m.employee_name; ``` ### 子查询 MySQL 的子查询是嵌套在另一个查询中的查询,子查询也称为内部查询,那些包含子查询的查询被称为外部查询。 可以在任何地方,在一个表达式中使用子查询。此外,必须用括号将子查询包起来。 查找单笔支付额最大的支付信息: ``` SELECT * FROM payment WHERE total_money = ( SELECT MAX(total_money) FROM payment ); ``` 查找所有在广州办公的雇员信息: ``` SELECT * FROM employee WHERE office_id IN ( SELECT office_id FROM office WHERE city = '广州' ); ``` 查找所有下过订单的客户信息: ``` SELECT * FROM customer WHERE EXISTS ( SELECT * FROM `order` WHERE customer.customer_id = `order`.customer_id ); ``` 查找所有未下过订单的客户信息: ``` SELECT * FROM customer WHERE NOT EXISTS ( SELECT * FROM `order` WHERE customer.customer_id = `order`.customer_id ); ``` exists 对外表逐条 loop 查询,每次查询都会查看 exists 的条件语句,当 exists 里的条件语句能够返回记录行时,返回当前 loop 到的这条记录,反之这条记录被丢弃。 ### 合并查询 MySQL UNION 运算符允许从多个表查询出来的结果集组合成一个结果集。语法如下: SELECT column1,column2 UNION[DISTINCT|ALL] SELECT column1,column2 UNION[DISTINCT|ALL] 查找编号为 1001 的顾客 2015-2017 每年前 10 条订单信息: ``` SELECT order_id,customer_id,order_date FROM order_2015 WHERE customer_id = 1001 LIMIT 10 UNION ALL SELECT order_id,customer_id,order_date FROM order_2016 WHERE customer_id = 1001 LIMIT 10 UNION ALL SELECT order_id,customer_id,order_date FROM order_2017 WHERE customer_id = 1001 LIMIT 10 ``` 使用 UNION 的注意点: - SELECT 语句列数量必须相等。 - SELECT 语句的列要有相同的数据类型,或至少是可转换的数据类型。 UNION DISTINCT 从结果集中清除重复行,UNION ALL 明确地保留重复行,UNION ALL 性能比 UNION DISTINCT 更好。 参考链接: - [MySQL 子查询](http://www.studymysql.com/mysql/subquery.html) - [MySQL UNION 用法](http://www.studymysql.com/mysql/union.html) - [MySQL 中 EXISTS 与 IN 的使用](http://www.cnblogs.com/beijingstruggle/p/5885137.html)