如何从薪资表中找到第三或第n个最高薪水?

Kar*_*dhi 95 sql sql-server sql-server-2008

如何以优化的方式third or nth从薪水table(EmpID,EmpName,EmpSalary)中找到最高薪水?

Kum*_*PMP 85

行号:

SELECT Salary,EmpName
FROM
  (
   SELECT Salary,EmpName,ROW_NUMBER() OVER(ORDER BY Salary) As RowNum
   FROM EMPLOYEE
   ) As A
WHERE A.RowNum IN (2,3)
Run Code Online (Sandbox Code Playgroud)

子查询:

SELECT *
FROM Employee Emp1
WHERE (N-1) = (
               SELECT COUNT(DISTINCT(Emp2.Salary))
               FROM Employee Emp2
               WHERE Emp2.Salary > Emp1.Salary
               )
Run Code Online (Sandbox Code Playgroud)

热门关键字:

SELECT TOP 1 salary
FROM (
      SELECT DISTINCT TOP n salary
      FROM employee
      ORDER BY salary DESC
      ) a
ORDER BY salary
Run Code Online (Sandbox Code Playgroud)


Tim*_*ter 77

使用ROW_NUMBER(如果你想要一个)或DENSE_RANK(对于所有相关的行):

WITH CTE AS
(
    SELECT EmpID, EmpName, EmpSalary,
           RN = ROW_NUMBER() OVER (ORDER BY EmpSalary DESC)
    FROM dbo.Salary
)
SELECT EmpID, EmpName, EmpSalary
FROM CTE
WHERE RN = @NthRow
Run Code Online (Sandbox Code Playgroud)

  • @BimalDas:那么您在“EmpSalary”列上没有索引。还有,相比什么减少了?`ROW_NUMBER` 方法的优点是你可以使用 `..OVER(PARTITION BY GroupColumn OrderBy OrderColumn)`。所以你可以用它来获取组,但仍然可以访问它的任何列。 (2认同)
  • @BimalDas:不,它不是创建临时表.cte通常不会在任何地方实现.它更像是内联视图或命名子查询. (2认同)
  • @KennyLJ:嗯,这是一个 SQL Server 问题,“LIMIT”是 MySql。在 MS-SQL-Server 中,您需要子查询或 CTE,因为您不能在“WHERE”中使用“ROW_NUMBER”。[为什么不能在`WHERE`子句中使用`ROW_NUMBER()`](https://www.sqltheater.com/2017/09/28/cant-use-row_number-where/) (2认同)

Cod*_*sen 60

试试这个

SELECT TOP 1 salary FROM (
   SELECT TOP 3 salary 
   FROM employees 
   ORDER BY salary DESC) AS emp 
ORDER BY salary ASC
Run Code Online (Sandbox Code Playgroud)

对于3你可以替换任何值...

  • 这个答案看起来很简单,适合初学者 (2认同)

Raj*_*oti 37

如果你想要优化方式意味着使用TOP关键字,那么第n个最大和最小工资查询如下,但通过使用聚合函数名称查询看起来像一个棘手的反向顺序:

N最高工资:

SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary DESC) 
Run Code Online (Sandbox Code Playgroud)

对于Ex:3最高薪水:

SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary DESC) 
Run Code Online (Sandbox Code Playgroud)

N最低工资:

SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary ASC)
Run Code Online (Sandbox Code Playgroud)

对于Ex:3最低工资:

SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary ASC)
Run Code Online (Sandbox Code Playgroud)

  • 为了获得我们在ASC订单中所做的最高工资,它必须以DESC顺序完成,如果我们有这样的工资7000,10000,11000,500,800,900,12000,那么排序的内部查询将导致top3意味着500,800,900这些最大值为900,但900不是3最大值,3最大值是10000. (4认同)

dev*_*rsh 14

如果你使用子查询太简单了!

SELECT MIN(EmpSalary) from (
SELECT EmpSalary from Employee ORDER BY EmpSalary DESC LIMIT 3
);
Run Code Online (Sandbox Code Playgroud)

您可以在此处更改LIMIT约束后的第n个值.

这里的Sub查询从雇员订单中选择EmpSalary DESC限制3; 将返回员工的前3名工资.在结果中,我们将使用MIN命令选择最低工资以获得员工的第3个TOP工资.


Luv*_*Luv 12

用最大数字替换N.

SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
Run Code Online (Sandbox Code Playgroud)

说明

如果您之前没有看到类似的内容,上面的查询可能会非常混乱 - 内部查询是所谓的相关子查询,因为内部查询(子查询)使用外部查询中的值(在本例中为Emp1表) )在它的WHERE子句中.

来源

  • +1 了解为什么 `... WHERE (N-1) = (Subquery)...` 有效很重要。子查询是一个相关查询,因为它的“WHERE”子句使用来自主查询的“Emp1”。每次主查询扫描一行时都会评估子查询。例如,如果我们要从 (800, 1000, 700, 750) 中找到第三大工资 (N=3),则第一行的子查询将是 `SELECT COUNT(DISTINCT(Emp2.Salary)) FROM Employee Emp2 WHERE Emp2。 Salary > 800` 为 0。对于第 4 个薪水值 (750) `... WHERE Emp2.Salary > 750` 将是 2 或 N-1,因此将返回该行。 (2认同)

小智 11

不使用子查询的工资表中的第三或第n个最高工资

select salary from salary
   ORDER   BY salary DESC
   OFFSET  N-1 ROWS
   FETCH NEXT 1 ROWS ONLY
Run Code Online (Sandbox Code Playgroud)

对于第3个最高薪水,2代替N-1

  • 值得一提的是,OFFSET FETCH可从SQL Server 2012 +版本获得. (2认同)

小智 10

SELECT Salary,EmpName
FROM
(
SELECT Salary,EmpName,DENSE_RANK() OVER(ORDER BY Salary DESC) Rno from EMPLOYEE
) tbl
WHERE Rno=3
Run Code Online (Sandbox Code Playgroud)


Sau*_*tel 10

SELECT EmpSalary 
FROM salary_table 
GROUP BY EmpSalary 
ORDER BY EmpSalary DESC LIMIT n-1, 1;
Run Code Online (Sandbox Code Playgroud)


Vij*_*att 7

请参阅以下查询以获得第n个最高薪水.通过这种方式,你在MYSQL中获得第n个最高薪水.如果你想获得第n个最低工资,你需要在查询中用ASC替换DESC. 第n个最高薪水


小智 5

在 2008 年,我们可以使用 ROW_NUMBER() OVER (ORDER BY EmpSalary DESC) 来获得我们可以使用的没有关系的排名。

例如,我们可以通过这种方式获得第 8 个最高值,或者将 @N 更改为其他内容或将其用作函数中的参数(如果您愿意)。

DECLARE @N INT = 8;
WITH rankedSalaries AS
(
SELECT
EmpID
,EmpName
,EmpSalary,
,RN = ROW_NUMBER() OVER (ORDER BY EmpSalary DESC)
FROM salary
)
SELECT
EmpID
,EmpName
,EmpSalary
FROM rankedSalaries
WHERE RN = @N;
Run Code Online (Sandbox Code Playgroud)

在 SQL Server 2012 中,您可能知道这是使用 LAG() 更直观地执行的。


小智 5

方法1:

SELECT TOP 1 salary FROM (
SELECT TOP 3 salary 
 FROM employees 
  ORDER BY salary DESC) AS emp 
 ORDER BY salary ASC
Run Code Online (Sandbox Code Playgroud)

方法2:

  Select EmpName,salary from
  (
    select EmpName,salary ,Row_Number() over(order by salary desc) as rowid      
     from EmpTbl)
   as a where rowid=3
Run Code Online (Sandbox Code Playgroud)


Shi*_*ala 5

从 SQL Server 的角度回答这个问题,因为这个问题发布在 SQL Server 部分。

\n

获得第 N 份薪水的方法有很多种,我们可以将这些方法分为两部分,一是使用 ANSI SQL 方法,二是使用 TSQL 方法。您还可以查看这个查找 第 n 个最高薪水的 YouTube 视频,该视频显示了实际的内容。让\xe2\x80\x99s 尝试涵盖编写此 SQL 的三种方法。

\n
    \n
  • 方法 1: - ANSI SQL: - 使用简单 order by 和 top 关键字。
  • \n
  • 方法 2: - ANSI SQL: - 使用关联子查询。
  • \n
  • 方法 3: - TSQL: - 使用 Fetch Next
  • \n
\n

在此输入图像描述

\n

方法 1: - 使用简单的 order by 和 top。

\n

在这种方法中,我们将使用 order by 和 top 关键字的组合。我们可以将思维过程分为 4 个步骤:-

\n

步骤 1: - 降序:- 无论我们有什么数据,首先使用 order by 子句使其降序。

\n

步骤 2:- 然后使用 TOP 关键字并选择 TOP N。其中 N 代表您想要的最高薪资排名。

\n

步骤 3: - 升序: - 使数据升序。

\n

第 4 步:- 选择顶部 1。您就完成了。

\n

在此输入图像描述

\n

因此,如果您在 SQL 中记下上述 4 个逻辑步骤,则会出现如下所示的结果。

\n

在此输入图像描述

\n

下面是 SQL 文本,如果您想执行和测试相同的 SQL 文本。

\n
\n

select top 1 * from (select top 2 EmployeeSalary from tblEmployee\norder by EmployeeSalary desc) 作为内部查询 order by EmployeeSalary\nasc

\n
\n

方法 1 的参数化问题

\n

方法 1 的最大问题之一是 \xe2\x80\x9cPARAMETERIZATION\xe2\x80\x9d。

\n

如果你想将上面的 SQL 封装到一个存储过程中,并以你想要的最高薪水作为参数输入,那么采用方法 1 会很困难。

\n

您可以使用方法 1 做的事情之一是使其成为动态 SQL,但这不是一个优雅的解决方案。让\xe2\x80\x99s 查看方法 2,这是一种 ANSI SQL 方法。

\n

方法 2: - 使用关联子查询。

\n

下面是相关子查询解决方案的样子。如果您是联合相关子查询的新手。关联子查询是查询中包含查询的查询。外部查询首先评估,将记录发送到内部查询,然后内部查询评估并将其发送到外部查询。

\n

查询中的\xe2\x80\x9c3\xe2\x80\x9d就是我们要查的最高工资。

\n
\n

从 tblEmployee 中选择 E1.EmployeeSalary 作为 E1,其中 3=(从 tblEmployee 中选择\ncount(*) 作为 E2 其中\nE2.EmployeeSalary>=E1.EmployeeSalary)

\n
\n

所以在上面的查询中我们有一个外部查询:-

\n
\n

从 tblEmployee 中选择 E1.EmployeeSalary 作为 E1

\n
\n

内部查询位于 where 子句中。观察那些 BOLD\xe2\x80\x99s,它们指示在 where 子句中如何引用外部表别名,这使得相互相关的内部和外部查询来回计算:-

\n
\n

其中 3=(从 tblEmployee 中选择 count(*) 作为 E2其中\nE2.EmployeeSalary>=E1.EmployeeSalary)

\n
\n

现在让 \xe2\x80\x99s 说你有 3000、4000、1000 和 100 这样的记录,所以下面是步骤:-

\n
    \n
  1. 前 3000 个将发送到内部查询。
  2. \n
  3. 内部查询现在将检查有多少记录值大于或等于 3000。如果记录计数不相等,它将采用下一个值,即 4000。现在对于 3000,只有 2 个值大于或等于、 3000 和 4000。那么,记录数是否为 2>-=3?.NO,所以它需要第二个值,即 4000。
  4. \n
  5. 再次计算 4000 有多少记录值大于或等于。如果记录数不相等,则取下一个值,即 1000。
  6. \n
  7. 现在1000有3条记录大于或等于1000,(3000、4000和1000他自己)。这是相关停止和退出并给出最终输出的地方。
  8. \n
\n

在此输入图像描述

\n

方法 3:- TSQL 获取和下一步。

\n

第三种方法是使用 TSQL。通过使用 Fetch 和 Next,我们可以轻松获得第 N 个最高值。

\n

但请注意,TSQL 代码不适用于其他数据库,我们需要再次重写整个代码。

\n

这将是一个三步过程:-

\n

第 1 步按降序区分和排序: - 首先应用区分和顺序,使工资降序排列并清除重复项。

\n

步骤 2 使用偏移量: - 使用 TSQL 偏移量并获取前 N-1 行。其中N是我们想要得到的最高薪水。偏移量采用指定的行数,保留其他行。为什么是(N-1),因为它是从零开始的。

\n

步骤 3 使用 Fetch: - 使用 fetch 并获取第一行。该行的工资最高。

\n

在此输入图像描述

\n

SQL 看起来如下所示。

\n

在此输入图像描述

\n

性能对比

\n

下面是性能比较的 SQL 计划。\n下面是 top 和 order by 的计划。

\n

在此输入图像描述

\n

以下是相关查询的计划。您可以看到操作员的数量非常多。因此,对于海量数据来说,相关性肯定会表现不佳。

\n

在此输入图像描述

\n

下面是比相关的 TSQL 查询计划更好的查询计划。

\n

在此输入图像描述

\n

所以,总结一下,我们可以进行更全面的比较,如下表所示。

\n

在此输入图像描述

\n