数据库 DQL:数据查询的艺术与实践
在数据库操作中,数据查询语言(DQL)是获取和处理数据的核心工具。它能够从数据库表中精准、高效地提取所需信息,满足各种业务场景下的数据查询需求。本文将详细介绍 DQL 的语法结构、各类查询方式,并结合 SQL 代码实例分析其应用场景。
DQL 的语法结构
DQL 的完整语法结构清晰且层次分明,各个子句按照特定的顺序协同工作,具体如下:
vbnet
SELECT
字段列表
FROM
表名字段
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后的条件列表
ORDER BY
排序字段列表
LIMIT
分页参数
并且,DQL 各子句的执行顺序为:FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT,这一顺序决定了数据处理的流程。
各类查询方式及实例
基础查询
基础查询是获取数据的最基本方式,主要用于查询表中的指定字段或所有字段,并可对字段进行别名设置、去除重复记录以及处理特殊字符转义。
- 查询多个字段:
语法为SELECT 字段1, 字段2, 字段3, ... FROM 表名;,例如从员工表(employee)中查询姓名和年龄字段:
sql
SELECT name, age FROM employee;
若要查询表中所有字段,可使用SELECT * FROM 表名;,如查询员工表的所有字段:
sql
SELECT * FROM employee;
但在实际开发中,不建议频繁使用*,因为它会查询所有字段,可能降低查询效率,且当表结构变化时,结果也会随之变化。
- 设置别名:
可以为查询的字段设置别名,使结果更易理解,语法为SELECT 字段1 [ AS 别名1 ], 字段2 [ AS 别名2 ], ... FROM 表名;,其中AS可省略。例如为员工表的姓名和年龄字段设置别名:
vbnet
SELECT name AS 员工姓名, age 员工年龄 FROM employee;
- 去除重复记录:
当查询的字段存在重复值时,可使用SELECT DISTINCT 字段列表 FROM 表名;去除重复记录。例如查询员工表中不重复的工作地址:
sql
SELECT DISTINCT workaddress FROM employee;
- 转义:
在模糊查询中,若要查询的内容包含通配符(如_或%),需要进行转义。语法为SELECT * FROM 表名 WHERE 字段 LIKE '转义符+通配符+其他内容' ESCAPE '转义符'。例如查询姓名为 "张三" 的员工(其中 " " 为普通字符):
sql
SELECT * FROM employee WHERE name LIKE '/_张三' ESCAPE '/';
这里/为转义符,使得后面的_不作为通配符。
条件查询
条件查询通过设置条件筛选出符合要求的数据,语法为SELECT 字段列表 FROM 表名 WHERE 条件列表;,其中条件可由比较运算符和逻辑运算符组合而成。
- 比较运算符:
-
-
:大于,如查询年龄大于 30 的员工:
-
sql
SELECT * FROM employee WHERE age > 30;
-
-
=:大于等于,如查询年龄大于等于 30 的员工:
-
sql
SELECT * FROM employee WHERE age >= 30;
-
- <:小于,如查询年龄小于 30 的员工:
sql
SELECT * FROM employee WHERE age < 30;
-
- <=:小于等于,如查询年龄小于等于 30 的员工:
sql
SELECT * FROM employee WHERE age <= 30;
-
- =:等于,如查询年龄等于 30 的员工:
ini
SELECT * FROM employee WHERE age = 30;
-
- <>或!=:不等于,如查询年龄不等于 30 的员工:
sql
SELECT * FROM employee WHERE age != 30;
-
- BETWEEN ... AND ...:在某个范围内(含最小、最大值),如查询年龄在 20 到 30 之间的员工:
sql
SELECT * FROM employee WHERE age BETWEEN 20 AND 30;
注意,若范围设置为BETWEEN 30 AND 20,则查询不到结果。
-
- IN(...) :在列表中的值,多选一,如查询年龄为 25、30 或 35 的员工:
sql
SELECT * FROM employee WHERE age IN (25, 30, 35);
-
- LIKE 占位符:模糊匹配(_匹配单个字符,%匹配任意个字符),如查询姓名为两个字的员工:
sql
SELECT * FROM employee WHERE name LIKE '__';
查询身份证最后为 X 的员工:
sql
SELECT * FROM employee WHERE idcard LIKE '%X';
-
- IS NULL:是 NULL,如查询没有身份证的员工(身份证字段为 NULL 或空字符串):
sql
SELECT * FROM employee WHERE idcard IS NULL OR idcard = '';
- 逻辑运算符:
-
- AND或&&:并且(多个条件同时成立),如查询性别为女且年龄小于 30 的员工:
ini
SELECT * FROM employee WHERE age < 30 AND gender = '女';
-
- OR或||:或者(多个条件任意一个成立),如查询年龄为 25 或 30 或 35 的员工(与 IN 用法类似):
ini
SELECT * FROM employee WHERE age = 25 OR age = 30 OR age = 35;
-
- NOT或!:非,不是,如查询年龄不大于 30 的员工:
sql
SELECT * FROM employee WHERE NOT age > 30;
聚合查询(聚合函数)
聚合查询用于对数据进行统计分析,常见的聚合函数包括 count(统计数量)、max(最大值)、min(最小值)、avg(平均值)、sum(求和),语法为SELECT 聚合函数(字段列表) FROM 表名;。
例如,统计工作地址为 "广东省" 的员工数量:
sql
SELECT count(id) FROM employee WHERE workaddress = "广东省";
查询员工的最大年龄:
sql
SELECT max(age) FROM employee;
查询员工的最小年龄:
sql
SELECT min(age) FROM employee;
查询员工的平均年龄:
sql
SELECT avg(age) FROM employee;
查询员工年龄总和:
sql
SELECT sum(age) FROM employee;
分组查询
分组查询用于将数据按照指定字段进行分组,然后对每个分组进行统计分析,语法为SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后的过滤条件 ];。
WHERE和HAVING的区别在于:
- 执行时机不同:WHERE是分组之前进行过滤,不满足WHERE条件的记录不参与分组;HAVING是分组后对结果进行过滤。
- 判断条件不同:WHERE不能对聚合函数进行判断,而HAVING可以。
例如,根据性别分组,统计男性和女性的数量:
csharp
select gender, count(*) from employee group by gender;
根据性别分组,统计男性和女性的平均年龄:
csharp
select gender, avg(age) from employee group by gender;
年龄小于 45,并根据工作地址分组:
csharp
select workaddress, count(*) from employee where age < 45 group by workaddress;
年龄小于 45,并根据工作地址分组,获取员工数量大于等于 3 的工作地址:
sql
select workaddress, count(*) address_count from employee where age < 45 group by workaddress having address_count >= 3;
需要注意的是,分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无实际意义;且执行顺序为where > 聚合函数 > having。
排序查询
排序查询用于对查询结果按照指定字段进行排序,语法为SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;,排序方式包括ASC(升序,默认)和DESC(降序)。
例如,根据年龄升序排序:
sql
SELECT * FROM employee ORDER BY age ASC;
-- 或省略ASC
SELECT * FROM employee ORDER BY age;
根据年龄升序排序,当年龄相同时,再按入职时间降序排序:
sql
SELECT * FROM employee ORDER BY age ASC, entrydate DESC;
分页查询
分页查询用于将大量查询结果分页展示,语法为SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数;。
例如,查询第一页数据,展示 10 条:
sql
SELECT * FROM employee LIMIT 0, 10;
查询第二页数据,展示 10 条:
sql
SELECT * FROM employee LIMIT 10, 10;
需要注意的是,起始索引从 0 开始,起始索引的计算公式为起始索引 = (查询页码 - 1) * 每页显示记录数;且分页查询是数据库的方言,不同数据库有不同实现,MySQL 中使用LIMIT;如果查询的是第一页数据,起始索引可以省略,直接简写为LIMIT 10。
应用场景分析
基础查询的应用场景
- 数据概览:当需要快速了解表中某些字段的基本信息时,使用基础查询获取多个字段或所有字段的数据,如查看员工的姓名、年龄和工作地址等基本信息。
- 数据去重分析:在统计不同类别的数据时,使用DISTINCT去除重复记录,如统计公司员工来自哪些不同的地区。
条件查询的应用场景
- 精准数据筛选:根据业务需求筛选出符合特定条件的数据,如查询年龄在 25-35 岁之间的女性员工,以便开展针对性的活动。
- 模糊搜索:在用户查询功能中,使用LIKE进行模糊匹配,如根据用户输入的关键词查询相关的员工姓名。
聚合查询的应用场景
- 数据统计分析:对数据进行统计,如统计公司员工的总人数、平均工资、最高年龄等,为企业决策提供数据支持。
- 业务指标计算:计算各类业务指标,如某产品的总销量、平均销售额等。
分组查询的应用场景
- 分类统计:按照不同类别对数据进行统计,如按部门分组统计各部门的员工人数、平均工资,便于了解各部门的人员结构和薪酬情况。
- 分组筛选:在分组的基础上进一步筛选出符合条件的分组,如按地区分组后,筛选出员工人数超过 100 人的地区。
排序查询的应用场景
- 数据排序展示:将查询结果按照指定顺序展示,如将员工按入职时间从早到晚排序,便于查看员工的入职先后顺序;将商品按销量从高到低排序,方便用户了解热门商品。
分页查询的应用场景
- 大量数据展示:当查询结果数据量较大时,使用分页查询分批次展示数据,如在网页上展示员工列表时,每页显示 20 条,用户通过翻页查看更多数据,提高页面加载速度和用户体验。
总之,DQL 作为数据查询的核心工具,其丰富的查询方式和灵活的语法能够满足各种复杂的查询需求。