Lit*_*les 33
您可以使用公用表表达式(CTE)来获得答案.
假设您在工资表中有以下工资:
EmployeeID Salary
--------------------
10101 50,000
90140 35,000
90151 72,000
18010 39,000
92389 80,000
Run Code Online (Sandbox Code Playgroud)
我们将使用:
DECLARE @N int
SET @N = 3 -- Change the value here to pick a different salary rank
SELECT Salary
FROM (
SELECT row_number() OVER (ORDER BY Salary DESC) as SalaryRank, Salary
FROM Salaries
) as SalaryCTE
WHERE SalaryRank = @N
Run Code Online (Sandbox Code Playgroud)
这将按照Salary按降序排序后为每一行创建一个行号,然后检索第三行(包含第三高的记录).
对于那些不想要CTE(或陷入SQL 2000)的人:
[ 注意:这比上面的例子明显更糟; 与exceution计划并排运行它们显示CTE的查询成本为36%,子查询的查询成本为64%]:
SELECT TOP 1 Salary
FROM
(
SELECT TOP N Salary
FROM Salaries
ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC
Run Code Online (Sandbox Code Playgroud)
其中N由您定义.
SalarySubquery
是我给子查询的别名,或括号中的查询.
子查询的作用是选择前N个工资(在这种情况下我们会说3个),并按最高工资对它们进行排序.
如果我们想要查看第三高的薪水,子查询将返回:
Salary
-----------
80,000
72,000
50,000
Run Code Online (Sandbox Code Playgroud)
外部查询然后从子查询中选择第一个薪水,除了我们这次按升序排序,从最小到最大排序,因此50,000将是第一个按升序排序的记录.
如您所见,50,000例确实是该示例中第三高的薪水.
And*_*mar 12
您可以使用row_number
选择特定行.例如,第42个最高薪水:
select *
from (
select row_number() over (order by Salary desc) as rn
, *
from YourTable
) as Subquery
where rn = 42
Run Code Online (Sandbox Code Playgroud)
窗口函数row_number
只能出现在select
或order by
子句中.解决方法是将row_number
子查询放在子查询中.
小智 6
select MIN(salary) from (
select top 5 salary from employees order by salary desc) x
Run Code Online (Sandbox Code Playgroud)
小智 5
EmpID Name Salary
1 A 100
2 B 800
3 C 300
4 D 400
5 E 500
6 F 200
7 G 600
SELECT * FROM Employee E1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(E2.Salary))
FROM Employee E2
WHERE E2.Salary > E1.Salary
)
Run Code Online (Sandbox Code Playgroud)
假设您想找到第五高的薪水,这意味着总共有4名员工的薪水高于第五高的员工。因此,对于外部查询的每一行,请检查比当前薪水高的薪水总数。外部查询将首先使用100,并检查薪水数量是否大于100。它将为6,与外部查询的(5-1) = 6
where子句不匹配。然后,对于800,检查薪水数量是否大于800,为4=0
false,然后为300工作,最后表中总共有4个记录大于300。因此,4=4
将满足where子句并返回
3 C 300
。