如何以优化的方式从工资中找到第三或第 n个最高工资?table(EmpID, EmpName, EmpSalary)
56 回答
行号:
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)
子查询:
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary
)
热门关键词:
SELECT TOP 1 salary
FROM (
SELECT DISTINCT TOP n salary
FROM employee
ORDER BY salary DESC
) a
ORDER BY salary
使用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
试试这个
SELECT TOP 1 salary FROM (
SELECT TOP 3 salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
对于 3,您可以替换任何值...
如果你想优化方式意味着使用TOP
关键字,所以第 n 个最大和最小薪水查询如下,但查询看起来很棘手,因为使用聚合函数名称以相反的顺序:
N 最高工资:
SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary DESC)
例如:3 最高工资:
SELECT MIN(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary DESC)
N 最低工资:
SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP N EmpSalary FROM Salary ORDER BY EmpSalary ASC)
例如:3 最低工资:
SELECT MAX(EmpSalary)
FROM Salary
WHERE EmpSalary IN(SELECT TOP 3 EmpSalary FROM Salary ORDER BY EmpSalary ASC)
如果使用子查询太简单了!
SELECT MIN(EmpSalary) from (
SELECT EmpSalary from Employee ORDER BY EmpSalary DESC LIMIT 3
);
您可以在此处仅更改 LIMIT 约束后的第 n 个值。
在此,子查询 Select EmpSalary from Employee Order by EmpSalary DESC Limit 3; 将返回员工的前 3 名工资。在结果中,我们将使用 MIN 命令选择最低薪水,以获得员工的第三个最高薪水。
用你的最大数量替换 N
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
解释
如果您以前没有见过类似的查询,上面的查询可能会很混乱——内部查询是所谓的相关子查询,因为内部查询(子查询)使用外部查询(在本例中为 Emp1 表)中的值) 在它的 WHERE 子句中。
和来源
工资表中的第三个或第 n 个最高工资,而不使用子查询
select salary from salary
ORDER BY salary DESC
OFFSET N-1 ROWS
FETCH NEXT 1 ROWS ONLY
对于第三高的薪水,用 2 代替 N-1
SELECT Salary,EmpName
FROM
(
SELECT Salary,EmpName,DENSE_RANK() OVER(ORDER BY Salary DESC) Rno from EMPLOYEE
) tbl
WHERE Rno=3
SELECT EmpSalary
FROM salary_table
GROUP BY EmpSalary
ORDER BY EmpSalary DESC LIMIT n-1, 1;
请参阅以下查询以获得第 n 高的薪水。通过这种方式,您将获得 MYSQL 中第 n 高的薪水。如果您只想获得第 n 个最低工资,则需要在查询中将 DESC 替换为 ASC。
方法一:
SELECT TOP 1 salary FROM (
SELECT TOP 3 salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
方法二:
Select EmpName,salary from
(
select EmpName,salary ,Row_Number() over(order by salary desc) as rowid
from EmpTbl)
as a where rowid=3
在 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;
在 SQL Server 2012 中,您可能知道这是使用 LAG() 更直观地执行的。
declare @maxNthSal as nvarchar(20)
SELECT TOP 3 @maxNthSal=GRN_NAME FROM GRN_HDR ORDER BY GRN_NAME DESC
print @maxNthSal
从表中获得第三高值
SELECT * FROM tableName ORDER BY columnName DESC LIMIT 2, 1
从 SQL Server 的角度回答这个问题,因为这发布在 SQL Server 部分。
获得第 N 薪水的方法有很多,我们可以将这些方法分为两个部分,一个使用 ANSI SQL 方法,另一个使用 TSQL 方法。您还可以查看这个找到 第 n 个最高薪水的 youtube 视频,它实际上展示了一些事情。让我们尝试涵盖三种编写此 SQL 的方法。
- 方法 1: - ANSI SQL: - 使用 Simple order by 和 top 关键字。
- 方法 2: - ANSI SQL: - 使用共同相关的子查询。
- 方法 3:- TSQL:- 使用 Fetch Next
方法 1: - 使用简单的 order by 和 top。
在这种方法中,我们将使用 order by 和 top 关键字的组合。我们可以将我们的思考过程分为 4 个步骤:-
第 1 步:- 降序:- 无论我们拥有什么数据,首先使用 order by 子句使其降序。
第 2 步:- 然后使用 TOP 关键字并选择 TOP N。其中 N 代表您想要的最高薪级。
第 3 步: - 升序: - 使数据升序。
第 4 步:- 选择前 1 项。您就完成了。
因此,如果您在 SQL 中记下上述 4 个逻辑步骤,则会出现如下所示的内容。
下面是 SQL 的文本,以防您想执行和测试它。
select top 1 * from (select top 2 EmployeeSalary from tblEmployee order by EmployeeSalary desc) as innerquery order by EmployeeSalary asc
方法一的参数化问题
方法 1 的最大问题之一是“参数化”。
如果您想将上述 SQL 包装到一个存储过程中,并输入您想要的最高薪水作为参数,则方法 1 会很困难。
使用方法 1 可以做的一件事是让它成为动态 SQL,但这不是一个优雅的解决方案。让我们看看方法 2,它是一种 ANSI SQL 方法。
方法 2: - 使用共同相关的子查询。
下面是相关子查询解决方案的外观。如果您不熟悉 Co-related 子查询。关联子查询是查询内查询的查询。外部查询首先评估,将记录发送到内部查询,内部查询然后评估并将其发送到外部查询。
查询中的“3”是我们要找出的最高薪水。
Select E1.EmployeeSalary from tblEmployee as E1 where 3=(Select count(*) from tblEmployee as E2 Where E2.EmployeeSalary>=E1.EmployeeSalary)
所以在上面的查询中,我们有一个外部查询:-
从 tblEmployee 中选择 E1.EmployeeSalary 作为 E1
内部查询在 where 子句中。注意那些指示外部表别名如何在 where 子句中引用的粗体,这使得相互关联的评估内部和外部查询:-
where 3=(Select count(*) from tblEmployee as E2 Where E2.EmployeeSalary>=E1.EmployeeSalary)
所以现在假设你有像 3000、4000、1000 和 100 这样的记录,所以下面是步骤: -
- 前 3000 个将被发送到内部查询。
- 内部查询现在将检查有多少记录值大于或等于 3000。如果记录数不相等,它将采用下一个值,即 4000。现在对于 3000,只有 2 个值大于或等于, 3000 和 4000。那么,数字记录计数是否 2>-=3?.NO,所以它需要第二个值,即 4000。
- 同样对于 4000 有多少记录值大于或等于。如果记录数不相等,则取下一个值,即 1000。
- 现在 1000 有 3 条记录大于或等于 1000,(3000,4000 和 1000 自己)。这是 co-related 停止和退出并给出最终输出的地方。
方法 3: - TSQL fetch 和 Next。
第三种方法是使用 TSQL。通过使用 Fetch 和 Next,我们可以轻松获得第 N 个最高值。
但请注意,TSQL 代码不适用于其他数据库,我们需要重新重写整个代码。
这将是一个三步过程:-
第 1 步 Distinct 和 Order by descending: - 首先应用 distinct 和 order 使工资下降以及清除重复项。
第 2 步使用偏移量: - 使用 TSQL 偏移量并获取前 N-1 行。其中 N 是我们想要得到的最高薪水。偏移量采用指定的行数,保留其他行。为什么是(N-1),因为它从零开始。
第 3 步使用 Fetch: - 使用 fetch 并获取第一行。那一排的薪水最高。
SQL 看起来如下所示。
性能比较
下面是性能比较的SQL计划。以下是顶部和排序的计划。
以下是相关查询的计划。您可以看到运营商的数量非常多。所以肯定 co-related 会对大量数据造成不良影响。
下面是比 cor-related 更好的 TSQL 查询计划。
因此,总结起来,我们可以更全面地进行比较,如下表所示。
这是任何 SQL 面试中的热门问题之一。我将写下不同的查询来找出列的第 n 个最高值。
我通过运行以下脚本创建了一个名为“Emloyee”的表。
CREATE TABLE Employee([Eid] [float] NULL,[Ename] [nvarchar](255) NULL,[Basic_Sal] [float] NULL)
现在我将通过运行下面的插入语句将 8 行插入到该表中。
insert into Employee values(1,'Neeraj',45000)
insert into Employee values(2,'Ankit',5000)
insert into Employee values(3,'Akshay',6000)
insert into Employee values(4,'Ramesh',7600)
insert into Employee values(5,'Vikas',4000)
insert into Employee values(7,'Neha',8500)
insert into Employee values(8,'Shivika',4500)
insert into Employee values(9,'Tarun',9500)
现在我们将使用不同的查询从上表中找出第三高的 Basic_sal。我在管理工作室中运行了以下查询,结果如下。
select * from Employee order by Basic_Sal desc
我们可以在上图中看到,第三高的基本工资是 8500。我正在写 3 种不同的方式来做同样的事情。通过运行下面提到的所有三个查询,我们将得到相同的结果,即 8500。
第一种方式: - 使用行号功能
select Ename,Basic_sal
from(
select Ename,Basic_Sal,ROW_NUMBER() over (order by Basic_Sal desc) as rowid from Employee
)A
where rowid=2
Select TOP 1 Salary as '3rd Highest Salary' from (SELECT DISTINCT TOP 3 Salary from Employee ORDER BY Salary DESC) a ORDER BY Salary ASC;
我显示第三高的薪水
SELECT MIN(COLUMN_NAME)
FROM (
SELECT DISTINCT TOP 3 COLUMN_NAME
FROM TABLE_NAME
ORDER BY
COLUMN_NAME DESC
) AS 'COLUMN_NAME'
--nth最高薪水
select *
from (select lstName, salary, row_number() over( order by salary desc) as rn
from employee) tmp
where rn = 2
--(nth -1) 最高薪水
select *
from employee e1
where 1 = (select count(distinct salary)
from employee e2
where e2.Salary > e1.Salary )
优化方式:不使用子查询,只使用limit。
select distinct salary from employee order by salary desc limit nth, 1;
通过子查询:
SELECT salary from
(SELECT rownum ID, EmpSalary salary from
(SELECT DISTINCT EmpSalary from salary_table order by EmpSalary DESC)
where ID = nth)
试试这个查询
SELECT DISTINCT salary
FROM emp E WHERE
&no =(SELECT COUNT(DISTINCT salary)
FROM emp WHERE E.salary <= salary)
把 n= 你想要的值
set @n = $n
SELECT a.* FROM ( select a.* , @rn = @rn+1 from EMPLOYEE order by a.EmpSalary desc ) As a where rn = @n
MySQL 测试解决方案,假设 N = 4:
select min(CustomerID) from (SELECT distinct CustomerID FROM Customers order by CustomerID desc LIMIT 4) as A;
另一个例子:
select min(country) from (SELECT distinct country FROM Customers order by country desc limit 3);
试试这个代码: -
SELECT *
FROM one one1
WHERE ( n ) = ( SELECT COUNT( one2.salary )
FROM one one2
WHERE one2.salary >= one1.salary
)
从表中找出第 N 个最高薪水。这是使用 dense_rank() 函数完成此任务的一种方法。
select linkorder from u_links
select max(linkorder) from u_links
select max(linkorder) from u_links where linkorder < (select max(linkorder) from u_links)
select top 1 linkorder
from ( select distinct top 2 linkorder from u_links order by linkorder desc) tmp
order by linkorder asc
DENSE_RANK : 1. DENSE_RANK 计算行在有序行组中的排名,并将排名作为数字返回。等级是从 1 开始的连续整数。 2. 此函数接受任何数字数据类型的参数并返回 NUMBER。3. 作为一个分析函数,DENSE_RANK 根据 order_by_clause 中 value_exprs 的值计算查询返回的每一行相对于其他行的排名。4. 在上面的查询中,排名是根据雇员表的sal 返回的。在平局的情况下,它为所有行分配相同的排名。
WITH result AS (
SELECT linkorder ,DENSE_RANK() OVER ( ORDER BY linkorder DESC ) AS DanseRank
FROM u_links )
SELECT TOP 1 linkorder FROM result WHERE DanseRank = 5
在 SQL Server 2012+ 中,OFFSET...FETCH 将是实现此目的的有效方法:
DECLARE @N AS INT;
SET @N = 3;
SELECT
EmpSalary
FROM
dbo.Salary
ORDER BY
EmpSalary DESC
OFFSET (@N-1) ROWS
FETCH NEXT 1 ROWS ONLY
select * from employee order by salary desc;
+------+------+------+-----------+
| id | name | age | salary |
+------+------+------+-----------+
| 5 | AJ | 20 | 100000.00 |
| 4 | Ajay | 25 | 80000.00 |
| 2 | ASM | 28 | 50000.00 |
| 3 | AM | 22 | 50000.00 |
| 1 | AJ | 24 | 30000.00 |
| 6 | Riu | 20 | 20000.00 |
+------+------+------+-----------+
select distinct salary from employee e1 where (n) = (select count( distinct(salary) ) from employee e2 where e1.salary<=e2.salary);
将 n 替换为第 n 个最高薪水作为数字。
SELECT TOP 1 salary FROM ( SELECT TOP n salary FROM employees ORDER BY salary DESC Group By salary ) AS emp ORDER BY salary ASC
(其中 n 代表第 n 个最高工资)
只需更改内部查询值:例如 Select Top (2)* from Student_Info order by ClassID desc
用于这两个问题:
Select Top (1)* from
(
Select Top (1)* from Student_Info order by ClassID desc
) as wsdwe
order by ClassID
要查询nth highest bonus
,比如说n=10
,使用 AdventureWorks2012,请尝试以下代码
USE AdventureWorks2012;
GO
SELECT * FROM Sales.SalesPerson;
GO
DECLARE @grade INT;
SET @grade = 10;
SELECT MIN(Bonus)
FROM (SELECT TOP (@grade) Bonus FROM (SELECT DISTINCT(Bonus) FROM Sales.SalesPerson) AS a ORDER BY Bonus DESC) AS g
select max(sal)
from emp
where sal > (
select max(sal)
from emp
where sal > (select max(sal) from emp)
);
另一种根据日期查找最后最高数据的方法
SELECT A.JID,A.EntryDate,RefundDate,Comments,Refund, ActionBy FROM (
(select JID, Max(EntryDate) AS EntryDate from refundrequested GROUP BY JID) A
Inner JOIN (SELECT JID,ENTRYDATE,refundDate,Comments,refund,ActionBy from refundrequested) B
ON A.JID=B.JID AND A.EntryDate = B.EntryDate)
要找到第 5 高的薪水:
Declare @N INT = 5
SELECT Salary FROM Employee
ORDER BY Salary DESC OFFSET @N - 1 ROW
嗨,还有一个使用公用表表达式编写此代码的示例:
with cte as
(SELECT TOP 3 salary
FROM salary
ORDER BY salary DESC)
select top 1 salary from cte
with cte as
(select e.Name,s.salary ,DENSE_RANK ()over ( order by salary desc) sal_rank
from salary s left join employee e
on s.EmpID=e.EmpID)
select Name,salary from cte where sal_rank=3
优化方式,
;With CTE as
(
select salary
,RANK(order by salary desc) as Rnk
from table
)
select * from CTE where Rnk = @yourVariable
第二个意见,
Declare @yourVariable int = 2
Select top 1 * from
(
select distinct top(@yourVariable) salary
from Employees
order by salary desc
)as a
order by a.salary asc
select * from Employees
order by salary desc
你可以试试这个:
select top(1) EXPORT_NO
from DC_HDR
order by CASE when (ROW_NUMBER() over(order by EXPORT_NO desc))=3 then EXPORT_NO else 0 end desc
select min(salary)
from (select salary
from employee
where rownum < n+1
order by salary desc);
显示所有第三高薪水:
select * from emp where sal=
(SELECT DISTINCT sal FROM emp ORDER BY sal DESC LIMIT 3,1) ;
仅显示第三高薪水:
SELECT DISTINCT sal FROM emp ORDER BY sal DESC LIMIT 3,1
select
Min(salary)
from ( select salary from employees order by salary desc) t
where rownum<=3;
对于第二高的薪水,在上面的查询中将 3 更改为 2,将第 N 高的薪水更改为 N,其中 N = 1,2,3,4....
试试这个...
SELECT MAX(salary) FROM employee WHERE salary NOT IN (SELECT * FROM employee ORDERBY salary DESC LIMIT n-1)
SELECT * FROM (select distinct Salary from Customers order by Salary DESC) 限制 4,1;
限制 4,1 表示保留前 4 行,然后选择下一行。
限制和行号取决于您使用的平台。
试试这个,它会工作的。
注意:请将查询中的OFFSET 3替换为任意第 N 个整数
SELECT EmpName,EmpSalary
FROM SALARY
ORDER BY EmpSalary DESC
OFFSET 3 ROWS
FETCH NEXT 1 ROWS ONLY
描述
仅获取下 1 行
仅返回 1 行
偏移 3 行
排除前3条记录在这里你可以给你任何整数
子查询总是需要更多时间:
使用以下查询获取任何最高和最低数据:
最高数据:select *from business order by id desc limit 3,1;
最低数据:select *from business order by id asc limit 3,1;
可以用 N 代替 3 得到第 n 个数据。
薪水第 n 高的行
(假设多个员工可以有相同的薪水;即可以存在联系)
如果您想要所有薪水最高的行
select * from table_name
where salary = (
select distinct(salary) as sal from
table_name order by sal desc
limit n-1, 1
);
如果您只想要第 n 高薪水的 FIRST k 行
select * from table_name
where salary = (
select distinct(salary) as sal from
table_name order by sal desc
limit n-1, 1
) limit k; -- you can also apply `order by` in this line
参考
//你可以从表中找到第n个薪水。如果你想检索第二高薪水然后放n = 2,如果第3 hs然后输出n = 3,依此类推..
SELECT * FROM tablename t1
WHERE (N-1) = (SELECT COUNT(DISTINCT(t2.Salary))
FROM tablename t2
WHERE t2.Salary > t1.Salary)
使用 CTE 和 FIRST_VALUE 函数查找第 N 个最大值。-- 5th 最高薪水
;WITH CTE_NTH_SAL AS
(SELECT FIRST_VALUE(ESAL) OVER(ORDER BY ESAL DESC) AS ESAL,
1 AS ID
FROM EMPLOYEE
UNION ALL
SELECT FIRST_VALUE(EMP.ESAL) OVER(ORDER BY EMP.ESAL DESC) AS ESAL,
ID
FROM EMPLOYEE EMP,
(SELECT ESAL,
ID+1 AS ID
FROM CTE_NTH_SAL) CTE_NTH_SAL
WHERE EMP.ESAL<CTE_NTH_SAL.ESAL
AND CTE_NTH_SAL.ID<=5 )
SELECT DISTINCT ESAL
FROM CTE_NTH_SAL
WHERE ID=5
对于示例结果集和更多方法,请单击此处
SELECT TOP 1 salary
FROM employee
WHERE salary IN (SELECT DISTINCT TOP 3 salary
FROM employee
ORDER BY salary DESC)
ORDER BY salary ASC
SELECT TOP 1 salary FROM (
SELECT TOP 3 salary
FROM employees
Group By salary ORDER BY salary DESC ) AS emp
ORDER BY salary ASC
这是用于从表 emp 中获取第 n 个最高薪水的 mysql 查询。我们在这里使用“LIMIT”作为“TOP”的替代,参数 (n-1) 显示从哪一行开始,第二个参数显示从第 (n-1) 行开始显示多少行。“LIMIT”也接受单个参数,它表示从第 0(或第 1)开始显示的行数。
select distinct * from emp order by sal desc limit (n-1),1;
declare @nHighestSalary as int
set @nHighestSalary = 3
SELECT TOP 1 salary FROM (
SELECT TOP @nHighestSalary salary
FROM employees
ORDER BY salary DESC) AS emp
ORDER BY salary ASC
第n高薪..
SELECT DISTINCT Salary
FROM EMP E WHERE
n =(SELECT COUNT(DISTINCT SALARY)
FROM EMP WHERE E.SALARY <= SALARY)
n 是您想要的最高值,即 2,3 等
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)
对于第 n个最高值
select min(salary)
from (select salary from(select salary from employee order by salary desc)where rownum<=n);
select * from emp x where &no=(select count(*) from emp y where y.sal>=x.sal);
这将从用户那里获取输入,然后告诉第 n 个最大数量。我在 oracle 中以 emp 表为例并显示第 n 个最大受薪员工信息
输出输入值:5
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ---------- --------- ---------- ---------- ----------
7698 BLAKE MANAGER 7839 01-MAY-81 3000 30
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7902 FORD ANALYST 7566 03-DEC-81 3000 20
输入值:14
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
select a.GRN_NAME
from GRN_HDR a,GRN_HDR b
where a.GRN_NAME<=b.GRN_NAME
group by a.GRN_NAME
having count(a.GRN_NAME)=3