--- title: "15-别名的妙用与limit分页" created: 2025-11-25 tags: - 项目筑基 --- # 别名的妙用与limit分页 ### \*别名的妙用 对比三条sql语句 (1)`Select ename,dname from emp,dept where emp.deptno=dept.deptno` (2)`Select emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno` (3)`Select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno` 功能一样 把职工表和部门表连接 找每个人所在的部门的名字 先回顾一下select进行的流程 拿着一个字段 遍历整个表 把它找出来 重点:遍历整个表 把两个表连接了也是一样 像第一种写法 经过的步骤是 拿着ename这个字段 从emp里面找 找到了 但是还没完 它还要去dept里去找这个ename字段 其实dept里压根没这个字段 做了无用功 dname同理 在emp表里做了无用功 白白把两个表都多遍历了一遍 这都是因为 ename和dname没有标明属于哪个表 所以有了第二种写法 这样emp.ename只要遍历emp表 dept.dname只要遍历dept表 效率提高了 ```sql Select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno ``` 用语句执行顺序分析 From emp和dept表 给emp表取别名叫e 给dept表取别名d(别名的AS 是可以省略的) WHERE 拿着表e的每一条记录 分别去与d表的每条记录匹配 匹配到deptno相同的就保留 Select 从e表中拿ename,d表中拿dname 进行一个组合 并显示出来 内部做的工作其实跟第二种一样 只是这个例子不能很好的显示出别名的妙用 只能说使得select后面不太冗长 要把多表查询玩出花来 必须得会取别名 对过程有了个大致的理解 其实不难看出 提高效率还有一个方面 尽量减少表的连接次数 连接越多 要进行的遍历就越多 效率越低 ![[image-38ffaae3.png]] 该执行的都执行了 只不过是把结果四选一 前面内连接里的自连接也用到了别名的概念 对于这样一张表 ![[image-555fa9b7.png]] 存储了所有员工 员工信息后面又对应了其领导的编号 那么想查询员工名对应的领导名怎么办 把一张表看成两张表 看成emp a 员工表 emp b 领导表 ![[image-72e30d10.png]] ![[image-b43a53ec.png]] ```sql Select a.ename as '员工名',b.ename as '领导名' from emp a join emp b on a.mgr = b.empno(员工的领导编号等于领导的员工编号) ``` 用别名 将表当成两个表 将mgr字段与empno字段进行连接 它其实就是一张表 但如果不使用别名 我们就无法去进行一个a.mgr = b.empno ![[image-411b1591.png]] 这个查询结果其实不全 因为king没有领导了 想要显示king怎么办 用到外连接 ```sql Select a.ename as '员工名',b.ename as '领导名' From emp a left join emp b on a.mgr=b.empno ``` ![[image-c1045442.png]] 把员工表a(其实就是emp整个表)作为主表(它在left的左边) 显示表a里所有的字段 把b表符合a.mgr=b.empno的字段加入这个表结构显示 但是 king不满足 那么就补充了NULL “捎带” 嵌套查询中也有很多例子 像这个from子句中的子查询 一个遗留问题 ![[image-dcbcde82.png]] ```sql from sc,(select sno,avg(grade) from sc group by sno) as avg_sc(avg_sno,avg_grade) Where sc.sno = avg_sc.avg_sno And grade > avg_sc.avg_grade ``` 分析一下其实也很清晰 从sc和这个虚拟表里查 但是这个虚拟表有两个字段 把它取个别名 整个表叫avg.sc 表里的sno字段叫做avg\_sno avg(grade)字段叫avg\_grade 可以当成这样: ```sql sc,(select sno as 'avg_sno',avg(grade) as 'avg_grade' from sc group by sno) as avg_sc ``` 不过长知识了 还能用这种很像结构体的写法 avg\_sc(avg\_sno,avg\_grade) 后面就很简单了 一个where筛选两个条件 就是把sc和这个虚拟表做个连接而已 所以现在看来别名的妙用: 使得代码不冗长简洁 但可读性会变差(不好理解) 使得代码执行效率更高 是某些操作(如自连接)的必要条件 子查询中为虚拟表命名以迎合自己的查询思路(如果给你两个存在的表那么很清楚应该怎么查 但如果是对一个查询结果进行操作 就有点懵了 所以用别名 把它当成真实存在的表) 别名的概念不仅在sql中体现 像c语言和数据结构中的typedef 都是一些操作的关键要素 ### limit分页 像百度等搜索引擎 查询出来的东西都是有分页的 limit就是限制结果的数量 达成分页效果 limit startIndex,length 起始下标、长度 `select ename,sal from emp order by sal desc limit 5` 缺省 取前五个 相当于 ```sql select ename,sal from emp order by sal desc limit 0,5 ``` limit在order by后面执行 取工资在3~5名的员工 起始下标是0 0 1 2 3 4 2开始 取长度3 所以2,3 `select ename,sal from emp order by sal desc limit 2,3` 如果[5~9] limit4,5 每页显示3条记录 第一页:limit 0,3 [012] 第二页limit 3,3 [345] 第三页limit 6,3 [678] 每页显示pagesize条记录 第pageno页:limit ?,pagesize ?(startIndex)等于(pageno-1)\*pagesize 如何实现浏览器一样 点击哪页就显示哪页数据 相当于是用户给出一个页码 又已有每页显示的记录条数 可以封装成 ```java public static void main(String[] args) { int pageNo=5; int pageSize=10; int startIndex=(pageNo-1)*pageSize; String sql="select … limit"+startIndex + "," + pageSize; } ``` 记`limit (pageno-1)*pagesize,pagesize` ### 大总结 from where group by having select order by limit 通过from查 用where进行筛选 筛选完了分组 分组后过滤 过滤后查出来 排序输出 排序后可能要取段 分页展示 --- ⬅️ [[14-子查询与结果集归并|14-子查询与结果集归并]] 🏠 [[00-数据库|00-数据库]] ➡️ [[16-导入导出|16-导入导出]]