分组查询(Group By)是在关系型数据库中用来对数据进行分组并对每个组应用聚合函数的一种操作。这种查询通常结合聚合函数(如 COUNT、SUM、AVG、MAX、MIN 等)使用,用于在查询结果中生成汇总信息
特点(聚合):输入多行,最终输出一行,且分组函数(COUNT、SUM、AVG、MAX、MIN)需要分组了才能使用,如果不进行分组则将会聚合整张表的数据
SELECT 字段1, 分组/聚合函数(字段2)
FROM 表名
WHERE 条件
GROUP BY 字段1;
分组查询的工作原理如下:
GROUP BY
子句中指定的列对数据进行分组。SELECT
中指定的聚合函数,计算每个分组的汇总值。计算某一列中的行数,或者符合特定条件的行数。
假设有一个 students
表,包含学生的信息,可以使用 COUNT() 函数来统计学生的总数或者符合某些条件的学生数。
-- 统计学生总数
SELECT COUNT(*) AS total_students
FROM students;
-- 统计年龄大于等于 18 岁的学生数
SELECT COUNT(*) AS adults
FROM students
WHERE age >= 18;
计算数值列的总和。
示例: 假设有一个 orders
表,包含订单信息,可以使用 SUM() 函数来计算订单总金额。
-- 计算所有订单的总金额
SELECT SUM(order_amount) AS total_amount
FROM orders;
-- 计算特定客户的订单总金额
SELECT customer_id, SUM(order_amount) AS total_spent
FROM orders
WHERE customer_id = 123
GROUP BY customer_id;
计算数值列的平均值。
示例: 继续使用 orders
表的例子,可以使用 AVG() 函数来计算平均订单金额。
sql-- 计算所有订单的平均金额
SELECT AVG(order_amount) AS average_amount
FROM orders;
-- 计算特定客户的平均订单金额
SELECT customer_id, AVG(order_amount) AS average_spent
FROM orders
WHERE customer_id = 123
GROUP BY customer_id;
找出数值列的最大值。
示例: 使用 MAX() 函数来查找订单表order
中的最高订单金额。
sql-- 找出订单表中的最高订单金额
SELECT MAX(order_amount) AS max_amount
FROM orders;
-- 找出每个客户的最高订单金额
SELECT customer_id, MAX(order_amount) AS max_spent
FROM orders
GROUP BY customer_id;
找出数值列的最小值。
示例: 使用 MIN() 函数来查找订单表order
中的最低订单金额。
-- 找出订单表中的最低订单金额
SELECT MIN(order_amount) AS min_amount
FROM orders;
-- 找出每个客户的最低订单金额
SELECT customer_id, MIN(order_amount) AS min_spent
FROM orders
GROUP BY customer_id;
从一张表中单独查询,称为单表查询。假设有a表和b表联合起来查询数据,从表a中取a1字段,从b表中取b1字段。这种跨表查询,多张表联合起来查询数据,被称为连接查询。
内连接:
外连接:
当两张表进行连接查询的时候,没有任何条件限制会发生笛卡尔积现象
例如A表有1000条数据,B表有200条数据,同时在链接查询时并没有去做表的连接限制,例如ON关键字(下面会讲),或者Where关键字,那么查询出的数据行数约:1000 * 200 = 200000条数据,且很大可能性没有任何质量
SELECT 字段
FROM 表1 INNER JOIN 表2 ON 表1.字段 = 表2.字段
WHERE 条件
-- orders 表和 customers 表通过 customer_id 列进行内连接,返回订单信息和对应客户的名称。
SELECT orders.order_id, customers.customer_name
FROM orders
INNER JOIN customers ON orders.customer_id = customers.customer_id;
SELECT 字段
FROM 表1 INNER JOIN 表2 ON 表1.字段 between 表2.字段1 and 表2.字段2
WHERE 条件
-- 找出员工的薪资等级
SELECT e.name,e.sal,s.grade
FROM emp e INNER JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
SELECT 字段
FROM 表1 INNER JOIN 表1 ON 表1.字段1 = 表1.字段2
WHERE 条件
-- 查询员工的上级领导
SELECT a.ename AS '员工名',b.ename AS '领导名'
FROM
emp a INNER JOIN emp b
a.mgr = b.empno
-- 语法
SELECT 列名 FROM 表1 LEFT JOIN 表2 ON 表1.列 = 表2.列
-- 返回所有客户的名称,以及他们的订单信息(如果有的话),如果客户没有订单,则订单信息列显示为 NULL
SELECT customers.customer_name, orders.order_id
FROM customers
LEFT JOIN orders ON customers.customer_id = orders.customer_id;
-- 语法
SELECT 列名 FROM 表1 RIGHT JOIN 表2 ON 表1.列 = 表2.列
-- 返回所有订单的信息,以及对应的客户名称,如果订单没有对应的客户信息,则客户名称列显示为 NULL。
SELECT orders.order_id, customers.customer_name
FROM orders
RIGHT JOIN customers ON orders.customer_id = customers.customer_id;
-- 语法
SELECT 列名 FROM 表1 FULL JOIN 表2 ON 表1.列 = 表2.列
-- 返回所有客户和订单的组合,无论是否有匹配的条件。
-- 如果某个客户没有订单或某个订单没有客户,则对应的列会显示 NULL。
SELECT customers.customer_name, orders.order_id
FROM customers
FULL JOIN orders ON customers.customer_id = orders.customer_id;
性能影响:连接操作可能会影响查询性能,特别是在大型数据集上或者未优化的情况下。
索引优化:在进行连接查询之前,确保相关的连接字段上存在适当的索引,可以提高查询效率。
结果集理解:理解不同类型连接查询的行为和生成的结果集,以避免数据丢失或者意外的数据组合。
查询语句中嵌套的select语句被称为子查询
子查询出现在如下部分:查询的字段列表中、FROM的临时表、WHERE的子条件,如下
SELECT 字段..,(子查询)
FROM ..,(子查询)
WHERE ..,(子查询)
现在有一张表为员工薪资表emp
SELECT ename,sal
FROM emp
WHERE sal > (SELECT MIN(sal) FROM emp)
from后的子查询,可以将子查询的结果当做一张临时表
SELECT
t.*,s.grade
FROM
(SELECT job,avg(sal) as avgsal FROM emp group by job) t
INNER JOIN
salgrade s
ON t.avgsal BETWEEN s.losal AND s.hisal
SELECT
e.ename,e.deptno,(SELECT d.dname FROM dept d WHERE e.deptno = d.deptno) as dname
FROM emp e