面试技术问题:无CTE/Top/子查询求第N高薪资及标识列迁移
嘿,这两个都是SQL开发里经常碰到的实际问题,我来给你分享下靠谱的解决方案:
问题1:不使用CTE、TOP、子查询获取第N高薪资
这里有个很简洁的方案,利用SQL的偏移量获取语法,不同数据库写法略有差异,但都不需要用到你说的那些禁用的语法:
适用于SQL Server 2012+、PostgreSQL、Oracle 12c+
用OFFSET ... FETCH语法,跳过前N-1条最高薪资的记录,然后取第1条:
-- 替换N为你要查询的具体数字,比如查第3高就填3 SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC OFFSET (N-1) ROWS FETCH NEXT 1 ROW ONLY;
- 加
DISTINCT是为了处理有重复薪资的场景,如果你的业务允许相同薪资算同一个排名,可以保留;如果不需要去重,直接去掉就行。 - 这个写法完全避开了CTE、TOP和子查询,完美符合要求。
适用于MySQL
MySQL用LIMIT语法实现类似效果:
SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT (N-1), 1;
如果N是变量的话,MySQL可能需要用预处理语句,但固定值直接这么写就可以。
问题2:复制带Identity列的数据并保留原ID值
Identity列默认是自动生成的,直接插入会报错,所以关键是先临时开启目标表的手动插入权限:
- 先打开表2的
IDENTITY_INSERT开关:
SET IDENTITY_INSERT Table2 ON;
- 执行插入语句,必须明确列出所有列名(包括ID列),不能用
SELECT *:
-- 把Column1、Column2替换成你实际的列名,要覆盖表中所有列 INSERT INTO Table2 (ID, Column1, Column2, Column3) SELECT ID, Column1, Column2, Column3 FROM Table1;
- 插入完成后,记得关闭开关恢复默认设置:
SET IDENTITY_INSERT Table2 OFF;
注意事项:
- 要确保表2中没有和表1重复的ID值,否则插入会报错;
- 两张表的结构必须完全匹配,包括列类型、长度等,不然可能出现数据转换错误。
内容的提问来源于stack exchange,提问作者Anandh
相关产品推荐
相关产品推荐

