SQL命令二:SQL 高级查询与特殊算法
引言
在掌握了 SQL 的基础操作和建表约束后,我们可以进一步探索 SQL 的高级查询功能和一些特殊算法。这些高级技巧能够帮助我们更高效地处理和分析数据,满足复杂的业务需求。
一、查询进阶
(一)简单查询
简单查询通过 select
语句实现,语法为 select 字段 from 表名 [别名]
。例如,在 employees
表中:
- 查询所有员工信息:
select * from employees;
- 查询员工姓名和薪资:
select ename, sal from employees;
- 使用别名查询:
select ename 姓名, sal 薪资 from employees;
- 去重查询岗位:
select distinct job from employees;
(二)限定查询
限定查询通过 where
子句实现条件筛选,支持多种比较运算符。例如:
- 查询薪资高于 2000 的员工信息:
select * from employees where sal > 2000;
- 查询薪资介于 1500 到 5000 的员工信息:
select * from employees where sal between 1500 and 5000;
-- 等价于
select * from employees where sal >= 1500 and sal <= 5000;
- 模糊查询:
- 查询名称中包含
S
的员工信息:select * from employees where ename like "%S%";
- 查询名称中第二个字母是
S
的员工信息:select * from employees where ename like "_S%";
- 查询名称中包含
- 查询入职日期在 1981 年的员工信息:
select * from employees where hiredate like '%1981%';
-- 更精确的查询
select * from employees where hiredate between '1981-01-01' and '1981-12-31';
- 查询员工编号在 7499、7521、7900 的员工信息:
select * from employees where empno = 7499 or empno = 7521 or empno = 7900;
-- 等价于
select * from employees where empno in (7499, 7521, 7900);
(三)排序查询
排序查询使用 order by
关键字,asc
表示升序,desc
表示降序。例如:
- 按入职日期降序排列:
select * from employees order by hiredate desc;
- 按薪资升序排列:
select * from employees order by sal asc;
- 多字段排序:
select * from employees order by deptno, sal desc;
先按部门编号排序,部门相同的再按薪资降序排列。
(四)多表查询
- 笛卡尔积查询:
select * from emp, dept;
这种查询方式简单地将两张表堆积在一起,会带来数据冗余问题,称为笛卡尔积效应。 - 消除笛卡尔积:通过追加关联条件,如
select * from emp, dept where emp.deptno = dept.deptno;
- 连接查询:
- 左(外)连接:
left(outer)join...on
,返回左表的所有行以及右表中匹配的行。例如,查询所有员工及其领导信息:
- 左(外)连接:
select e1.empno 员工编号, e1.ename 员工姓名, e1.sal 员工薪资, e2.empno 领导编号, e2.ename 领导姓名, e2.sal 领导薪资
from emp e1 left join emp e2 on e1.mgr = e2.empno;
- 右(外)连接:
right(outer)join...on
,返回右表的所有行以及左表中匹配的行。例如,查询所有员工及部门信息:
select e.empno 员工编号, e.ename 员工姓名, e.sal 薪资, d.deptno 部门编号, d.dname 部门名称
from emp e right join dept d on e.deptno = d.deptno;
- SQL1999 语法:
- 交叉连接:
join
会出现笛卡尔积,如select * from emp join dept;
- 自然连接:
natural join
自动提取相同字段,并放在最前面,如select * from emp natural join dept;
- join...on:指定连接条件,如
select * from emp join dept on emp.deptno = dept.deptno;
- join...using:指定连接字段,会把字段放到最前面,如
select * from emp join dept using(deptno);
- 交叉连接:
(五)分组查询
分组查询基于 group by
关键字,适用于需要对数据进行分组统计的场景。例如:
- 查询各部门人数:
select deptno, count(empno) 人数 from emp group by deptno;
- 统计各部门平均工资:
select deptno, avg(sal) 平均工资 from emp group by deptno;
分组后如需筛选,使用having
子句。例如,查询平均薪资高于 2000 的部门信息:
select deptno, avg(sal) 平均工资 from emp group by deptno having avg(sal) > 2000;
(六)子查询
1、where 子查询:当查询的结果为单行单列或多行单列时使用。例如:
- 查询比
smith
工资高的人:select * from emp where sal > (select sal from emp where ename = 'smith');
- 查询与销售岗位薪资相同的员工信息:
select * from emp where sal in (select sal from emp where job = 'salesman');
select * from emp where sal = any (select sal from emp where job = 'salesman');
2、from 子查询:当查询到的结果为多行多列时使用。例如,查询部门编号、部门名称、部门位置、部门人数和平均薪资的信息:
select d.deptno, d.dname, d.loc, count(e.empno) 人数, avg(e.sal) 平均薪资
from dept d left join emp e on d.deptno = e.deptno
group by e.deptno;
也可以使用子查询实现相同的功能。
(七)分页查询
分页查询使用 limit
关键字,语法为 limit start, count
,start
表示数据下标索引,count
表示每页条数。当 start
为 0 时可省略。例如,查询前十条员工信息:
select * from emp limit 0, 10;
-- 等价于
select * from emp limit 10;
二、特殊算法与约束
(一)雪花算法
雪花算法(Snowflake Algorithm)是一种分布式唯一 ID 生成算法,最早由 Twitter 开发,用于解决高并发环境下生成全局唯一 ID 的问题。
- ID 结构:生成的是一个 64 位的整数 ID,结构如下:
| 1 位符号位 | 41 位时间戳 | 10 位机器信息 | 12 位序列号 |
详细分解:- 符号位:永远为 0,表示正整数。
- 时间戳:当前时间与起始时间戳的差值,单位为毫秒,能使用约 69 年。
- 机器 ID(工作机器 + 数据中心):标识不同节点,一般为 5 位数据中心 ID + 5 位机器 ID。
- 序列号:每毫秒内的序号,支持每台机器每毫秒生成 4096 个 ID。
- 优点:
- 高性能:本地生成,无需数据库访问,生成一个 ID 只需几微秒。
- 全局唯一:由时间戳 + 机器号 + 序列号共同决定,天然不会重复。
- 趋势递增:基于时间戳生成,保证 ID 大致按生成时间递增,方便排序。
- 适合分布式系统:支持多节点并行生成不冲突的 ID。
- 缺点:
- 依赖机器时钟:如果系统时间回拨,可能会导致 ID 重复。
- 位数固定:64 位中各部分长度写死,扩展性有限。
- 不适合生成短 ID 或可读性强的 ID:生成的 ID 是类似 879278326123438080 的长整型数字。
(二)检查约束(CK)
在 MySQL 8.0.16 以下版本中,虽然可以设置检查约束,但实际并不生效。例如:
CREATE TABLE employees (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100),age INT,CONSTRAINT age_check CHECK(age >= 18 AND age <= 65)
);
建议在程序中处理业务逻辑,数据库专注于数据存储。
三、多对多关系与权限管理
在数据库设计中,多对多关系常见于权限管理等场景。例如,用户与角色、角色与菜单之间存在多对多关系。可以通过中间表来实现这种关系,如用户表、用户角色表、角色表、角色菜单表和菜单表。
- 动态权限:通过中间表动态关联用户、角色和菜单,实现灵活的权限分配。
- 静态权限:预先定义好的权限设置,相对固定。
总结
本文介绍了 SQL 的高级查询功能,包括简单查询、限定查询、排序查询、多表查询、分组查询、子查询和分页查询等。同时,探讨了雪花算法等特殊算法以及检查约束。掌握这些高级技巧和特殊算法,能够让我们在处理复杂的数据场景时更加得心应手,为数据分析和管理提供强大的支持。