关于数据库中写sql的问题,感觉最常见的就是薪水方面的

拿到一道sql题,首先感觉一下,可能会出现的问题,比如这道题,薪水问题,薪水会不会出现同名同薪的问题??要怎么考虑? 又比如mysql怎么写?如果是orcale呢?oracle有窗口函数,那么mysql呢?

排名是数据库中的一个经典题目,实际上又根据排名的具体细节可分为3种场景
同薪不同名,排名类似于编号,连续排名,例如薪水3000、2000、2000、1000排名结果为1-2-3-4
同薪同名但总排名不连续,例如同样的薪水分布,排名结果为1-2-2-4
同薪同名且总排名连续,同样的薪水排名结果为1-2-2-3。
不同的应用场景可能需要不同的排名结果,也意味着不同的查询策略。
本题的目标是实现第三种排名方式下的第N个结果,且是全局排名,不存在分组的问题,实际上还要相对简单一些。

所以拿到一个有排名问题的sql题,还需要考虑,需要不需要分组排序? 还是说是全局排序? 使用 order by 还是group by? 还是组合使用?

思路1:单表查询
由于本题不存在分组排序,只需返回全局第N高的一个,所以自然想到的想法是用order by排序加limit限制得到。需要注意两个细节:

同薪同名且不跳级的问题,解决办法是用group by按薪水分组后再order by
排名第N高意味着要跳过N-1个薪水,由于无法直接用limit N-1,所以需先在函数开头处理N为N=N-1。
注:这里不能直接用limit N-1是因为limit和offset字段后面只接受正整数(意味着0、负数、小数都不行)或者单一变量(意味着不能用表达式),也就是说想取一条,limit 2-1、limit 1.1这类的写法都是报错的。
注:这种解法形式最为简洁直观,但仅适用于查询全局排名问题,如果要求各分组的每个第N名,则该方法不适用;而且也不能处理存在重复值的情况。

思路2:窗口函数,其实就是一个范围,就是先规定了一个范围。
实际上,在mysql8.0中有相关的内置函数,而且考虑了各种排名问题:
主要涉及到的函数就是

  1. row_number():同薪不同名的,3000,2000,2000,1000,排名就是,1,2,3,4;
  2. rank():同薪同名,但是跳级的,也就是不连续,3000,2000,2000,1000,排名就是,1,2,2,4;
  3. dense_rank():同薪同名且不跳级,也就是连续的:3000,2000,2000,1000,排名就是,1,2,2,3;
  4. ntile(): 分桶排名,即首先按桶的个数分出第一二三桶,然后各桶内从1排名,实际不是很常用.

而我们这题,需要使用是dense_rank(),另外这三个函数必须要与其搭档over()配套使用,over()中的参数常见的有两个,分别是
partition by,按某字段切分
order by,与常规order by用法一致,也区分ASC(默认)和DESC,因为排名总得有个依据。

要注意版本,以下是8.0 才支持的。

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGINRETURN (# Write your MySQL query statement below.  select DISTINCT salary(select salary,dense_rank() over(order by salary desc) as rnkfrom Employee) tmpWHERE N = rnk;);
END

至此,可以总结MySQL查询的一般性思路是:

能用单表优先用单表,即便是需要用group by、order by、limit等,效率一般也比多表高

不能用单表时优先用连接,连接是SQL中非常强大的用法,小表驱动大表+建立合适索引+合理运用连接条件,基本上连接可以解决绝大部分问题。但join级数不宜过多,毕竟是一个接近指数级增长的关联效果

能不用子查询、笛卡尔积尽量不用,虽然很多情况下MySQL优化器会将其优化成连接方式的执行过程,但效率仍然难以保证

自定义变量在复杂SQL实现中会很有用,例如LeetCode中困难级别的数据库题目很多都需要借助自定义变量实现

如果MySQL版本允许,某些带聚合功能的查询需求应用窗口函数是一个最优选择。除了经典的获取3种排名信息,还有聚合函数、向前向后取值、百分位等,具体可参考官方指南。

每日一道SQL题(第N高的薪水)相关推荐

  1. 每日一道SQL题(二)

    一.627. 变更性别 给定一个 salary 表,如下所示,有 m = 男性 和 f = 女性 的值.交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然).要求只使用一个更新(Up ...

  2. 【每日一道智力题】之猴子搬香蕉

    题目 一个小猴子边上有100根香蕉,它要走过50米才能到家,每次它最多搬50根香蕉,(多了就被压坏了),它每走1米就要吃掉一根,请问它最多能把多少根香蕉搬到家里.(提示:他可以把香蕉放下往返的走,但是 ...

  3. 【每日一道智力题】之聪明的犯人!

    题目: 一百个犯人站成一纵列,每人头上随机带上黑色或白色的帽子,各人不知道自己帽子的颜色,但是能看见自己前面所有人帽子的颜色. 然后从最后一个犯人开始,每人只能用同一种声调和音量说一个字:" ...

  4. 【每日一道智力题】之高楼扔只因蛋

    目录 前言: 题目: 解析: 总结: 博客主页:张栩睿的博客主页 欢迎关注:点赞+收藏+留言 系列专栏:c语言学习         家人们写博客真的很花时间的,你们的点赞和关注对我真的很重要,希望各位 ...

  5. 【每日一道智力题】之海盗分金币(上)

    文章目录 题目: 解答: 题目变形: 解答: 总结 题目: 5个海盗抢到了100枚金币,每一颗都一样的大小和价值. 他们决定这么分: 抽签决定自己的号码(1,2,3,4,5) 首先,由1号提出分配方案 ...

  6. 简单的一道 SQL 题,谈如何提高编程水平

    点击蓝色"有关SQL"关注我哟 加个"星标",天天与12238人一起快乐成长 前两天发了一篇<SQL的3列4种对比方法>,近500 阅读.一个月没更 ...

  7. 【每日一道智力题】之 药瓶毒鼠鼠

    题目: 有1000个一模一样的瓶子,其中有999瓶是普通的水,有1瓶是毒药.任何喝下毒药的生命都会在一星期之后死亡.现在你只有10只鼠鼠和1个星期的时间,如何检验出哪个瓶子有毒药? 这是一道经典的面试 ...

  8. LeetCode刷题(176).第二高的薪水

    编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) . +----+--------+ | Id | Salary | +----+--------+ | 1  | 10 ...

  9. postgresql 遍历字符串数组_每日一道编程题(348):1005.K次取反后最大化的数组和...

    1005.K次取反后最大化的数组和 每日编程中遇到任何疑问.意见.建议请公众号留言或直接撩Q474356284(备注每日编程) 给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引  ...

最新文章

  1. 高考舞弊案背后的“文化魔咒”—— 如何整顿学风?(教育的失败!社会的...)...
  2. tf.reduce_sum()方法深度解析
  3. Android中的IPC机制
  4. 程序员每天少吃 能活120岁
  5. 智慧酒店:锐捷网络打造的完美酒店
  6. python adb控制手机制作剑气除魔游戏辅助
  7. android判断是否json格式,简单方法判断字符串是否是json字符串
  8. react native 渐变 BVLinearGradient报错不存在
  9. rsyslog收集华为路由器日志通过ELK处理展示
  10. ESP32接入米家-小爱同学-IDF环境-巴法平台
  11. pycharm无法识别turtle库中函数名的解决方法
  12. 系统更新荣耀play服务器,华为宣布:荣耀Play推送EMUI 9.1正式版更新!
  13. STM32+ENC28J60+UIP协议栈实现WEB服务器示例
  14. 【单例深思】枚举实现单例原理
  15. 金山软件刘鑫:有限使用UML
  16. 手机共享服务器文件夹,数据共享 手机怎么访问电脑文件?多个设备之间数据共享...
  17. 怎么使用python统计人名_python中人名最多统计
  18. Oracle高级查询之over(partition by...) 分组排序
  19. PTTLINK SYSTEM|对讲机对接详细方案
  20. java程序:求100以内质数的方法(两种方法)?

热门文章

  1. 从0开始创建一个MFC单文档工程
  2. 具有路线规划功能的外卖平台(Qt,C++,C/S架构,MySql)
  3. 苹果手机充电口接触不良怎么办_手机充电插口松动!声音变小!手机死机!怎么办?...
  4. java中栈的两种实现
  5. 设备维护管理的内容是什么?这四点你必须知道
  6. python 颜色与字体
  7. ARM平台处理器简介-ARMv7
  8. 【接口调用】EasyCVR获取直播流接口调用过程
  9. buu-[ACTF新生赛2020]rome
  10. python pyecharts 下载生成的render图片 下载背景为黑色