如何使用纯SQL获得第n个最高值?

时间:2013-01-07 12:56:09

标签: sql

使用纯SQL从结果集中获取第n个最高值的最简单方法是什么?

结果集很大,因此也需要考虑性能......

8 个答案:

答案 0 :(得分:2)

这是使用ROW_NUMBER的T-SQL(SQL-Server 2005及更高版本)方法:

WITH CTE AS
(
   SELECT 
      Col1, Col2, ValueCol,
      RN = ROW_NUMBER() OVER (ORDER BY ValueCol DESC) -- change to ASC if you want lowest first
   FROM 
      dbo.TableName
)
SELECT 
   Col1, Col2, ValueCol
FROM 
   CTE
WHERE 
   RN = @nthhighestvalue

如果您希望所有具有相同值的行都改为使用DENSE RANK

Difference between ROW_NUMBER, RANK and DENSE_RANK

答案 1 :(得分:0)

首先生成有序的编号数据集,然后从中进行选择。精确的语法取决于RDBMS,但是,例如,在Oracle中,您可以执行

SELECT ROWNUM, SOMEVAL
FROM (SELECT SOMEVAL FROM SOMETABLE ORDER BY SOMEVAL DESC)

鉴于以上设定,您可以

SELECT SOMEVAL WHERE ROWNUM = :N

答案 2 :(得分:0)

在通用数据库中,您可以使用子查询和两个order by来执行此操作。问题是top / limit / rownum语法不是标准的。在某些数据库中,您可以写:

答案 3 :(得分:0)

在Oracle中:

SELECT * FROM (
  SELECT col1, ROW_NUMBER()OVER(ORDER BY col1) rnum_col1 FROM table1
) WHERE rnum_col1 = 10;

答案 4 :(得分:0)

假设您要找到第5个最高薪水,您首先按降序排列第5个不同的工资单,以便最后一个是第5个最高薪水(参见内部查询)。然后按升序重新排序并取第一个。

SELECT TOP 1 Salary FROM
(
  SELECT DISTINCT TOP 5 Salary
  FROM Employee
  ORDER BY Salary DESC)  t

ORDER BY  Salary ASC

答案 5 :(得分:0)

This article深入讨论这个问题,我将从下面引用代码:

解决方案1:这个SQL找到第N个最高工资应该适用于SQL Server,MySQL,DB2,Oracle,Teradata以及几乎任何其他RDBMS :(注意:由于子查询而性能较低)

SELECT * /*This is the outer query part */
FROM Employee Emp1
WHERE (N-1) = ( /* Subquery starts here */
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)

在上面的查询中要理解的最重要的事情是,每次外部查询处理行时,都会对子查询进行求值。换句话说,内部查询不能独立于外部查询进行处理,因为内部查询也使用Emp1值。

为了找到第N个最高工资,我们只找到N-1工资大于其自身的工资。


解决方案2:使用SQL Server中的TOP关键字查找第n个最高薪水

SELECT TOP 1 Salary
FROM (
      SELECT DISTINCT TOP N Salary
      FROM Employee
      ORDER BY Salary DESC
      ) AS Emp
ORDER BY Salary

解决方案3:在不使用TOP

的情况下,在SQL Server中找到第n个最高薪水
SELECT Salary FROM Employee 
ORDER BY Salary DESC OFFSET N-1 ROW(S) 
FETCH FIRST ROW ONLY

请注意,我没有亲自测试上面的SQL,我相信它只能在SQL Server 2012及更高版本中运行。


解决方案4:在MySQL中运行

SELECT Salary FROM Employee 
ORDER BY Salary DESC LIMIT n-1,1

LIMIT子句在该查询中接受两个参数 - 第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。


解决方案5:适用于Oracle

select * from (
  select Emp.*, 
row_number() over (order by Salary DESC) rownumb 
from Employee Emp
)
where rownumb = n;  /*n is nth highest salary*/

解决方案6:以Oracle方式2工作

select * FROM (
select EmployeeID, Salary
,rank() over (order by Salary DESC) ranking
from Employee
)
WHERE ranking = N;

答案 6 :(得分:0)

子查询将列出最高的“ n”个最高薪水值。从该列表中,最小值将是第n个最高薪水。

`SELECT min(salary) FROM
    (SELECT DISTINCT TOP n salary FROM EmployeeTable ORDER BY salary desc);`

例如:-SQL查询以查找第三高薪

`SELECT min(salary) FROM
    (SELECT DISTINCT TOP 3 salary FROM EmployeeTable ORDER BY salary desc);`

答案 7 :(得分:-1)

你必须承担排序的开销,在我的例子中rownum是排序的行号,而不是物理位置。

由于每个人都在使用分析函数来显示这是如何工作的:

   select foo,bar, max(baz)  
    from  
    (
       select *   
      from  
      (  
          select foo,bar,baz, row_number() over 
          (partition by some_identifier_that_Groups order by  value DESC) rn 
      )    
       where rn = 1  -- get the highest value for each partition    
    ) group by foo,bar