【LeetCode刷题】SQL-Second Highest Salary 及扩展以及Oracle中的用法

   2023-02-10 学习力0
核心提示:题目: Write a SQL query to get the second highest salary from the Employee table. +----+--------+| Id | Salary |+----+--------+| 1| 100|| 2| 200|| 3| 300|+----+--------+ For example, given the above Employee table, the query should re

题目:

 

Write a SQL query to get the second highest salary from the Employee table.

 

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

 

For example, given the above Employee table, the query should return 200 as the second highest salary. If there is no second highest salary, then the query should return null

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+

 

Subscribe to see which companies asked this question.

 

翻译:

题目的意思是,在Employee表中找到第二大的Salary字段,然后以别名“SecondHighestSalary ”的形式输出

 

解题思路:

本题有两种思路。

一种是找到找到最大值,然后我们取比最大值小一点的最大值。

SQL:

SELECT Max(Salary) as SecondHighestSalary FROM Employee WHERE Salary< ( SELECT  Max(Salary) FROM Employee);

 

 Max()函数表示返回最大值,如果没有则返回NULL。

Salary<( SELECT Max(Salary) FROM Employee) 则是子查询的概念。

例如 Select * From Table_A Where key in (a,b);  如果其中(a,b)的数据来源于Table_B或者Table_A表。我们就可以使用子查询,将(a,b)的数据替换为我们查询到的数据。

Select * From Table_A Where key in (Select a,b From Table_B  Where Inr='XXXXXXX');

“as XXX”则表示将输出的数据以“XXX”为别名的方式输出。

 

还有一种方法就是,我们将数据进行排序,然后取第二位数。这种方法的难点在于:1、数据可能会有重复项。2、需要先排序再取数,所以不能用between 方法因为between方法必须要在order by 之前。3、整个表都是同一个数据的极端情况。

要解决以上3个难点。我们首先使用DISTINCT方法将数据的重复项过滤只剩一条,然后使用LIMIT分页的方法取第二个值,对于情况3中的极端情况,我们使用 IFNULL来进行判断,如果没取到值就返回NULL。需要注意的是,LIMIT是MySQL中的用法,Oracle是不支持LIMIT的。

SQL:

SELECT IFNULL( (SELECT distinct Salary  FROM Employee order by Salary desc limit 1,1),null)as SecondHighestSalary;

其中LIMIT 的用法是这样的:

LIMIT m,n      "m"表示偏移量,表示从第几位开始取。"n"表示长度,即需要取多少位。需要注意的是偏移量的第一位为0,所以"LIMIT 1,1"表示从第二位开始取长度为1的数也就是第二位数。"LIMIT 0,n"或者"LIMIT n "则表示从第一位开始取,一直取到第n位为止。"LIMIT m,-1"表示从第m位开始取,一直取到表的末尾。

distinct 表示将查询到的结果过滤重复项,只保留一项。

IFNULL(Exp1,Exp2),类似一个三元表达式,如果Exp1不为空则返回Exp1的结果集,如果为空就返回Exp2.

 

方法二的关键点在于排序和取数,排序我们除了使用ORDER BY 方法之外,还可以使用比较的方式排序。

SQL:

SELECT DISTINCT(e2.Salary) FROM Employee e1,Employee e2 WHERE e2.Salary>=e1.Salary;

使用“>=”的方式,是为了避免Salary字段有0值而导致无法比较。

需要注意的是,这种排序方式非常非常的消耗系统资源,在实际生产中使用这种方式来排序是不负责任的行为,所以如非必要尽量不要使用这种方式而使用更快捷消耗更小的的Order by。

现在已经排好序了,那么接下来我们要进行取数。取数可以使用上面的LIMIT方法。

LIMIT方法:

SELECT IFNULL((SELECT DISTINCT(e2.Salary) FROM Employee e1,Employee e2 WHERE e2.Salary>e1.Salary LIMIT 1,1),NULL) as SecondHighestSalary;

即,将:order by Salary desc 替换为 WHERE e2.Salary>e1.Salary 

除此之外还有其他方法吗?我们知道,SELECT语句实际上是个循环语句,既然是个循环语句而且已经排好序,那么也就是说如果我们要取第二大的数据,我们可以取当他循环到第二次时的那一行。怎么取到那一行呢。学过For循环都知道,要先对这个循环进行计数,然后循环到我们需要的那一次再取值。那么SQL中怎么计数呢。答案是使用COUNT方法。

COUNT方法

SELECT e1.Salary FROM Employee e1 WHERE 2=(Select Count(distinct(e2.Salary)) from Employee e2 where e2.Salary >= e1.Salary)  as SecondHighestSalary;

上面两种方法也可以用于,取任意第N位数据时。

COUNT方法之所以不能使用Order by,是因为Order by是对结果进行排序,而我们需要的是已排序好的结果。

 如果要使用Order by 方法,需要再加一层子查询。

COUNT-Order By 方法

SELECT Salary FROM Employee  WHERE 2=(Select Count(distinct(Salary)) from (Select Salary From Employee order by Salary desc))  as SecondHighestSalary;

.

由于Oracle中不能使用LIMIT,所以我们用rownum来处理此问题

Select Salary from (select amt ,rownum n From (Select distinct amt from Employee order by Salary desc)) where n=2;

其中的n=2可以替换为任意正整数,即为第N位。

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • sql:mysql:函数:TIMESTAMPDIFF函数实现TimeStamp字段相减,求得时间差
    sql:mysql:函数:TIMESTAMPDIFF函数实现TimeS
     函数内指定是minute,则最终结果value值的单位是分钟,如果函数内指定为hours,则最终结果value值单位为小时。//UPLOAD_TIME 减去 CREATE_DTTM 求得时间差,以分钟数计时select avg(TIMESTAMPDIFF(MINUTE,CREATE_DTTM,UPLOAD_TIME)) value,LEFT(CREATE_DTTM
    03-08
  • 去重复的sql(Oracle) 去重复的英文
    1.利用group by 去重复2.可以利用下面的sql去重复,如下  1) select id,name,sex from (select a.*,row_number() over(partition by a.id,a.set order by name) su from test a ) where su=1  2)select id,name,sex from (select a.*,row_number() over(p
    02-10
  • Oracle SQL七次提速技巧
    以下SQL执行时间按序号递减。1,动态SQL,没有绑定变量,每次执行都做硬解析操作,占用较大的共享池空间,若共享池空间不足,会导致其他SQL语句的解析信息被挤出共享池。create or replace procedure proc1as beginfor i in 1..100000 loop    execute imme
    02-10
  • Oracle\SQL  Server等及其他基本语句写法
    Oracle\SQL Server等及其他基本语句写法
    Oracle\SQL  Server等及其他基本语句写法目录一.Excel相关 11.Excel中写脚本范例: 12.提取字节 23. 提取单元格内字符 24.VLOOKUP函数: 2二.SQL语句汇总 21.建表: 22.增 33.删 44.查 65.改 236.Alter的应用 24三.数据库备份与恢复脚本 261. Oracle: 2
    02-10
  • SQL ORACLE case when函数用法
    case when 用法(1)简单case函数:格式:  case 列名   when 条件值1 then 选项1  when 条件值1 then 选项2......  else 默认值 end例如:  select   case job_level  when '1' then '1111'  when '2' then '2222'   when '3' then '3333
    02-10
  • mysql下如何执行sql脚本 执行SQL脚本
    1.编写sql脚本,假设内容如下:  create database dearabao;  use dearabao;  create table niuzi (name varchar(20));  保存脚本文件,假设我把它保存在F盘的hello world目录下,于是该文件的路径为:F:\hello world\niuzi.sql2.执行sql脚本,可以有2种方法: 
    02-10
  • MySQL 5.7版本sql_mode=only_full_group_by问题
    用到GROUP BY 语句查询时com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'col_user_6.a.START_TIME' which is not functionally dependent on colu
    02-10
  • Oracle迁移到MySQL性能下降的注意点 oracle数据
    背景:最近有较多的客户系统由原来由Oracle改造到MySQL后出现了性能问题CPU 100%,或是后台的CRM系统复杂SQL在业务高峰的时候出现堆积导致业务故障。在我的记忆里面淘宝最初从Oracle迁移到MySQL期间也遇到了很多SQL的性能问题,记忆最为深刻的子查询,当初的
    02-10
  • ORACLE中通过SQL语句(alter table)来增加、删除
    1.添加字段:alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ;2.添加备注:comment on column  库名.表名.字段名 is  '输入的备注';  如: 我要在ers_data库中  test表 document_type字段添加备注  comm
    02-10
  • MySQL与Oracle 差异比较之六触发器
    触发器编号类别ORACLEMYSQL注释1创建触发器语句不同create or replace trigger TG_ES_FAC_UNIT  before insert or update or delete on ES_FAC_UNIT  for each rowcreate trigger `hs_esbs`.`TG_INSERT_ES_FAC_UNIT` BEFORE INSERT on `hs_esbs`.`es_fac_u
    02-10
点击排行