数据库自连接(self join)本质上就是一个表和自己 join,分页思路和普通查询一样,只是先 join,再分页。下面按常见数据库分别说明,并给出注意事项。
示例表:
emp (
id,
name,
manager_id
)
自连接:查员工及其经理
SELECT
e.id,
e.name AS emp_name,
m.name AS manager_name
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.id
ORDER BY e.id;
SELECT
e.id,
e.name AS emp_name,
m.name AS manager_name
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.id
ORDER BY e.id
LIMIT 10 OFFSET 0;
LIMIT 10 OFFSET 10;
✅ 简单直观
⚠️ 深分页(OFFSET 很大)性能差
SELECT
e.id,
e.name AS emp_name,
m.name AS manager_name
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.id
ORDER BY e.id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
SELECT *
FROM (
SELECT
e.id,
e.name AS emp_name,
m.name AS manager_name,
ROW_NUMBER() OVER (ORDER BY e.id) rn
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.id
)
WHERE rn BETWEEN 11 AND 20;
避免 OFFSET 深分页问题。
SELECT
e.id,
e.name AS emp_name,
m.name AS manager_name
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.id
WHERE e.id > :last_id
ORDER BY e.id
LIMIT 10;
✅ 性能稳定
❌ 不支持“跳页”
✅ 用 唯一键 + 排序字段
ORDER BY e.id
先聚合,再分页:
WITH t AS (
SELECT e.manager_id, COUNT(*) cnt
FROM emp e
GROUP BY e.manager_id
)
SELECT * FROM t
ORDER BY cnt DESC
LIMIT 10;
| 方式 | 适用场景 |
|---|---|
| LIMIT/OFFSET | 小数据、前端分页 |
| OFFSET FETCH | SQL Server |
| ROW_NUMBER | Oracle |
| 游标分页 | 大数据、高性能 |
如果你有具体数据库 + SQL,我可以直接帮你改写分页版本。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。