数据如何查询

分组查询

分组查询(Group By)是在关系型数据库中用来对数据进行分组并对每个组应用聚合函数的一种操作。这种查询通常结合聚合函数(如 COUNT、SUM、AVG、MAX、MIN 等)使用,用于在查询结果中生成汇总信息

特点(聚合):输入多行,最终输出一行,且分组函数(COUNT、SUM、AVG、MAX、MIN)需要分组了才能使用,如果不进行分组则将会聚合整张表的数据

语法

sql 复制代码
SELECT 字段1, 分组/聚合函数(字段2)
FROM 表名
WHERE 条件
GROUP BY 字段1;

分组查询的工作原理如下:

  • 数据库首先按照 GROUP BY 子句中指定的列对数据进行分组。
  • 然后,对每个分组应用 SELECT 中指定的聚合函数,计算每个分组的汇总值。
  • 最后,返回每个分组的汇总结果作为查询结果集。
注意事项
  • 必须包含在 SELECT 子句中的列:在使用 GROUP BY 子句时,SELECT 子句中的列要么是分组列,要么是聚合函数。非聚合函数列必须包含在 GROUP BY 子句中,否则将导致语法错误。
  • NULL 值处理:分组查询中,数据库会将 NULL 值视为一个分组。
  • 性能考虑:当数据量较大时,分组查询可能会影响性能,尤其是在没有正确索引支持的情况下。

聚合/分组函数

COUNT

计算某一列中的行数,或者符合特定条件的行数。

假设有一个 students 表,包含学生的信息,可以使用 COUNT() 函数来统计学生的总数或者符合某些条件的学生数。

sql 复制代码
-- 统计学生总数
SELECT COUNT(*) AS total_students
FROM students;

-- 统计年龄大于等于 18 岁的学生数
SELECT COUNT(*) AS adults
FROM students
WHERE age >= 18;
SUM

计算数值列的总和。

示例: 假设有一个 orders 表,包含订单信息,可以使用 SUM() 函数来计算订单总金额。

sql 复制代码
-- 计算所有订单的总金额
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;
AVG

计算数值列的平均值。

示例: 继续使用 orders 表的例子,可以使用 AVG() 函数来计算平均订单金额。

sql 复制代码
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

找出数值列的最大值。

示例: 使用 MAX() 函数来查找订单表order中的最高订单金额。

sql 复制代码
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

找出数值列的最小值。

示例: 使用 MIN() 函数来查找订单表order中的最低订单金额。

sql 复制代码
-- 找出订单表中的最低订单金额
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字段。这种跨表查询,多张表联合起来查询数据,被称为连接查询。

连接查询的应用场景
  • 关联查询:用于在多个表中检索相关联的数据,比如客户和订单、产品和订单等。
  • 数据整合:将多个表中的数据整合为一个结果集,便于分析和报告。
  • 复杂条件过滤:通过连接不同表,并结合条件过滤,可以实现复杂的数据查询和分析需求。
  • 数据分析和报表:连接查询可以帮助生成更具体和详细的报表,涵盖多个业务方面的数据。
表连接的方式分类

内连接:

  • 等值连接
  • 非等值连接
  • 自连接

外连接:

  • 左外连接(左连接)
  • 右外连接(右连接)
  • 全连接(FULL JOIN)
⚠️注意避免笛卡尔积

当两张表进行连接查询的时候,没有任何条件限制会发生笛卡尔积现象

例如A表有1000条数据,B表有200条数据,同时在链接查询时并没有去做表的连接限制,例如ON关键字(下面会讲),或者Where关键字,那么查询出的数据行数约:1000 * 200 = 200000条数据,且很大可能性没有任何质量

语法

内连接查询(AB两个表没有主次关系)
  • 等值连接
sql 复制代码
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;
  • 非等值连接
sql 复制代码
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
  • 自连接
    • 自连接就是同一张表进行连接查询
sql 复制代码
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
外连接(AB两个表有主次关系)
  • 左连接(Left Join)
    • 左连接返回左边表(即左表)中的所有行,以及右表中满足连接条件的行。如果右表中没有匹配的行,则返回 NULL 值。
sql 复制代码
-- 语法
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;
  • 右连接(Right Join)
    • 右连接与左连接类似,不同之处在于它返回右表中的所有行,以及左表中满足连接条件的行。如果左表中没有匹配的行,则返回 NULL 值。
sql 复制代码
-- 语法
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;
  • 全连接(Full Join):
    • 全连接返回左表和右表中所有的行,无论是否满足连接条件。
sql 复制代码
-- 语法
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的子条件,如下

sql 复制代码
SELECT 字段..,(子查询)
FROM ..,(子查询)
WHERE ..,(子查询)

现在有一张表为员工薪资表emp

where中的子查询
  • 利用where子查询找出工资最低的员工信息
sql 复制代码
SELECT ename,sal 
FROM emp 
WHERE sal > (SELECT MIN(sal) FROM emp)
from中的子查询

from后的子查询,可以将子查询的结果当做一张临时表

  • 利用from子查询找出每个岗位的平均工资的薪资等级
sql 复制代码
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中的子查询
  • 利用select的子查询实现根据员工编号获取员工的部门名称
sql 复制代码
SELECT 
e.ename,e.deptno,(SELECT d.dname FROM dept d WHERE e.deptno = d.deptno) as dname
FROM emp e
相关推荐
Elastic 中国社区官方博客2 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪4 小时前
两次连接池泄露的BUG
java·数据库
南宫乘风5 小时前
基于 Flask + APScheduler + MySQL 的自动报表系统设计
python·mysql·flask
TDengine (老段)5 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349845 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE6 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy12393102166 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎6 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
杨云龙UP7 小时前
【MySQL迁移】MySQL数据库迁移实战(利用mysqldump从Windows 5.7迁至Linux 8.0)
linux·运维·数据库·mysql·mssql
l1t7 小时前
利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型
c语言·数据库·单元测试·lua·duckdb