MySQL查询详解
MySQL提供了丰富的查询指令,以下是一些常用的:
基本查询
SELECT 所有
用于从一个或多个表中检索数据,是最基本也是最常用的查询语句。
可以选择指定的列,也可以使用*
选择所有列。
例如:SELECT * FROM users;
会从users
表中检索所有列的数据,而SELECT name, age FROM users;
则只检索name
和age
两列的数据。
查询所有客户信息:
SELECT * FROM customers;
查询客户姓名和电子邮件:
SELECT customer_name, email FROM customers;
DISTINCT 去重
用于去除查询结果中的重复行。
例如SELECT DISTINCT country FROM customers;
会返回customers
表中country
列的所有不重复的值。
查询不同的国家:
SELECT DISTINCT country FROM customers;
条件查询
WHERE 条件
用于在查询中设置筛选条件,只返回满足条件的行。
例如SELECT * FROM products WHERE price > 100;
会从products
表中筛选出价格大于100的所有产品记录。
查询来自美国的客户:
SELECT * FROM customers WHERE country = 'USA';
BETWEEN 范围
用于筛选出在某个范围内的值。
例如SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
会返回orders
表中订单日期在2024年1月1日至2024年12月31日之间的所有记录。
查询2023年10月1日至2023年12月31日之间的订单:
SELECT * FROM orders WHERE order_date BETWEEN '2023-10-01' AND '2023-12-31';
IN 列表
用于判断某个值是否在给定的列表中。
例如SELECT * FROM students WHERE major IN ('Computer Science', 'Mathematics');
会从students
表中筛选出专业为计算机科学或数学的所有学生记录。
查询类别为'Electronics'或'Books'的产品:
SELECT * FROM products WHERE category IN ('Electronics', 'Books');
排序查询
用于对查询结果按照指定的列进行排序。
ORDER BY 排序
可以使用ASC
表示升序(默认),DESC
表示降序。
例如SELECT * FROM employees ORDER BY salary DESC;
会按照工资从高到低对employees
表中的记录进行排序。
按价格降序排列产品:
SELECT * FROM products ORDER BY price DESC;
分组查询
GROUP BY 分组
用于按照指定的列对结果进行分组,通常与聚合函数一起使用。例如SELECT department, COUNT(*) FROM employees GROUP BY department;
会按照部门对employees
表中的记录进行分组,并统计每个部门的员工数量。
按客户分组统计订单数量:
SELECT customer_id, COUNT(order_id) AS order_count FROM orders GROUP BY customer_id;
HAVING 筛选
用于在分组查询后对分组结果进行筛选,类似于WHERE
用于筛选行,而HAVING
用于筛选分组。
例如SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) > 5000;
会先按照部门分组计算平均工资,然后筛选出平均工资大于5000的部门。
查询订单数量大于1的客户:
SELECT customer_id, COUNT(order_id) AS order_count FROM orders GROUP BY customer_id HAVING COUNT(order_id) > 1;
连接查询
JOIN 用于将两个或多个表根据一定的条件连接起来进行查询,常见的有INNER JOIN
(内连接)、LEFT JOIN
(左连接)、RIGHT JOIN
(右连接)和FULL JOIN
(全连接)。
例如SELECT orders.order_id, customers.customer_name FROM orders INNER JOIN customers ON orders.customer_id = customers.customer_id;
会将orders
表和customers
表通过customer_id
字段进行内连接,返回订单编号和客户姓名。
查询客户姓名及其订单:
SELECT customers.customer_name, orders.order_id FROM customers JOIN orders ON customers.customer_id = orders.customer_id;
理解 :
- INNER JOIN 交集
- LEFT JOIN 左合集
- RIGHT JOIN 右合集
- FULL JOIN 合集
子查询
SELECT
子查询:子查询是嵌套在其他查询中的查询语句,可以出现在WHERE
、FROM
、HAVING
等子句中。
例如SELECT * FROM products WHERE price > (SELECT AVG(price) FROM products);
会从products
表中筛选出价格大于平均价格的所有产品记录。
查询价格高于平均价格的产品:
SELECT * FROM products WHERE price > (SELECT AVG(price) FROM products);
聚合函数查询
COUNT
:用于统计查询结果的行数或某列的非空值数量。例如SELECT COUNT(*) FROM users;
会返回users
表中的总行数,而SELECT COUNT(email) FROM users;
会返回email
列的非空值数量。SUM
:用于计算某列的数值总和。例如SELECT SUM(salary) FROM employees;
会计算employees
表中所有员工工资的总和。AVG
:用于计算某列的平均值。例如SELECT AVG(score) FROM students;
会计算students
表中所有学生成绩的平均值。
COUNT 行数
统计客户数量:
SELECT COUNT(*) AS customer_count FROM customers;
SUM 总和
计算总销售额:
SELECT SUM(quantity * price) AS total_sales FROM order_items JOIN products ON order_items.product_id = products.product_id;
AVG 平均
计算平均订单价值:
SELECT AVG(total_order_value) AS average_order_value FROM (SELECT SUM(quantity * price) AS total_order_value FROM order_items JOIN products ON order_items.product_id = products.product_id GROUP BY order_id) AS order_values;
限制查询
LIMIT
:用于限制查询结果返回的行数。例如SELECT * FROM products LIMIT 10;
会返回products
表中的前10条记录。OFFSET
:与LIMIT
一起使用,用于指定从哪一行开始返回结果。例如SELECT * FROM products LIMIT 5 OFFSET 10;
会从第11行开始返回5条记录。
LIMIT 返回数量
获取前2个客户:
SELECT * FROM customers LIMIT 2;
OFFSET 返回范围
获取第3和第4个客户 (假设每页2条记录):
SELECT * FROM customers LIMIT 2 OFFSET 2;
JOIN 模拟
以下是使用INNER JOIN
(内连接)、LEFT JOIN
(左连接)、RIGHT JOIN
(右连接)和FULL JOIN
(全连接,在MySQL中可以通过UNION
操作模拟实现全连接效果)的示例代码,假设有两张表:students
(学生表)和courses
(课程表),用于展示学生与课程之间的关联关系,表结构及示例数据如下:
学生表(students)
student_id | student_name |
---|---|
1 | 张三 |
2 | 李四 |
3 | 王五 |
课程表(courses)
course_id | course_name |
---|---|
101 | 数学 |
102 | 英语 |
103 | 物理 |
同时,还有一张关联表student_courses
(用于记录学生选修课程的对应关系),结构及示例数据如下:
学生选修课程表(student_courses)
student_id | course_id |
---|---|
1 | 101 |
1 | 102 |
2 | 101 |
3 | 103 |
以下是基于上述表结构和数据的不同连接查询示例:
1. INNER JOIN(内连接)
内连接会返回两个表中满足连接条件的匹配行。
-- 查询选修了课程的学生及其所选课程信息
SELECT s.student_name, c.course_name
FROM students s
INNER JOIN student_courses sc ON s.student_id = sc.student_id
INNER JOIN courses c ON sc.course_id = c.course_id;
执行结果示例:
student_name | course_name |
---|---|
张三 | 数学 |
张三 | 英语 |
李四 | 数学 |
王五 | 物理 |
解释:通过内连接,只有在students
表、student_courses
表以及courses
表中都能匹配上相应student_id
和course_id
的记录才会被返回,也就是只有选修了课程的学生及其对应的课程信息会显示出来。
2. LEFT JOIN(左连接)
左连接会返回左表(写在JOIN
关键字左边的表)中的所有行,以及与右表(写在JOIN
关键字右边的表)中满足连接条件的匹配行,如果右表中没有匹配行,则对应的列显示为NULL
。
-- 查询所有学生以及他们选修的课程信息(若未选修则课程相关列显示为NULL)
SELECT s.student_name, c.course_name
FROM students s
LEFT JOIN student_courses sc ON s.student_id = sc.student_id
LEFT JOIN courses c ON sc.course_id = c.course_id;
执行结果示例:
student_name | course_name |
---|---|
张三 | 数学 |
张三 | 英语 |
李四 | 数学 |
王五 | 物理 |
未选课学生(假设存在) | NULL |
解释:以students
表作为左表,无论学生是否选修了课程,都会显示学生的姓名,对于选修了课程的学生,会显示对应的课程名称,而没有选修课程的学生,课程名称那一列则显示为NULL
。
3. RIGHT JOIN(右连接)
右连接会返回右表中的所有行,以及与左表中满足连接条件的匹配行,如果左表中没有匹配行,则对应的列显示为NULL
。
-- 查询所有课程以及选修了这些课程的学生信息(若某课程无人选修则学生相关列显示为NULL)
SELECT s.student_name, c.course_name
FROM students s
RIGHT JOIN student_courses sc ON s.student_id = sc.student_id
RIGHT JOIN courses c ON sc.course_id = c.course_id;
执行结果示例:
student_name | course_name |
---|---|
张三 | 数学 |
李四 | 数学 |
张三 | 英语 |
王五 | 物理 |
NULL | 未被选课程(假设存在) |
解释:以courses
表作为右表,无论课程有没有学生选修,都会显示课程名称,对于有学生选修的课程,会显示选修该课程的学生姓名,而没有学生选修的课程,学生姓名那一列则显示为NULL
。
4. FULL JOIN(全连接,MySQL中通过UNION
模拟)
全连接会返回两个表中的所有行,当某一行在另一个表中没有匹配行时,对应的列显示为NULL
。
-- 通过UNION模拟全连接,查询所有学生与所有课程的对应关系(无论是否选修)
SELECT s.student_name, c.course_name
FROM students s
LEFT JOIN student_courses sc ON s.student_id = sc.student_id
LEFT JOIN courses c ON sc.course_id = c.course_id
UNION
SELECT s.student_name, c.course_name
FROM students s
RIGHT JOIN student_courses sc ON s.student_id = sc.student_id
RIGHT JOIN courses c ON sc.course_id = c.course_id;
执行结果示例(假设存在未选课学生和未被选课程):
student_name | course_name |
---|---|
张三 | 数学 |
张三 | 英语 |
李四 | 数学 |
王五 | 物理 |
未选课学生(假设存在) | NULL |
NULL | 未被选课程(假设存在) |
解释:
- 先通过左连接获取包含所有学生以及其对应课程(没选课则课程列为
NULL
)的结果集, - 再通过右连接获取包含所有课程以及选修学生(没学生选则学生列为
NULL
)的结果集, - 最后使用
UNION
将这两个结果集合并起来,去除重复行(因为UNION
默认会去除重复行),就模拟出了全连接的效果,展示出所有学生与所有课程的关联情况(无论是否实际存在选修关系)。