1

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

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

4

8 回答 8

2

这篇文章深入讨论了这个问题,我将在下面引用它的代码:

解决方案 1:这个找到第 N 高薪的 SQL 应该适用于 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 的薪水。


解决方案二:在 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;
于 2014-02-05T18:08:06.397 回答
2

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

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改用。

ROW_NUMBER、RANK 和 DENSE_RANK 之间的区别

于 2013-01-07T12:58:50.447 回答
0

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

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

鉴于上述设置,您可以

SELECT SOMEVAL WHERE ROWNUM = :N
于 2013-01-07T13:01:37.480 回答
0

在甲骨文中:

SELECT * FROM (
  SELECT col1, ROW_NUMBER()OVER(ORDER BY col1) rnum_col1 FROM table1
) WHERE rnum_col1 = 10;
于 2013-01-07T19:58:23.523 回答
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
于 2013-03-10T20:39:22.133 回答
0

在一般数据库中,您可以使用一个子查询和两个order bys. 问题是 top/limit/rownum 语法不是标准的。在某些数据库中,您会编写:

于 2013-01-07T14:21:16.153 回答
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);`
于 2020-07-14T05:42:07.713 回答
-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
于 2013-01-07T12:57:38.603 回答