IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 第一篇博客-Sql排名函数DENSE_RANK -> 正文阅读

[大数据]第一篇博客-Sql排名函数DENSE_RANK

Sql排名函数?DENSE_RANK

1、DENSE_RANK函数介绍

dense_rank函数用于返回结果集的分区内每行的排名,函数考虑到了over子句中排序字段值相同的情况,over子句中排序字段值相同的序号是一样的,后面字段值不相同的生成序号也是连续的。比如1、2、2、3。

相比较而言,另一个排名函数rank()与之类似,但是字段值不相同的序号将跳过相同的排名号排下一个,比如1、2、2、4。

dense_rank函数用法如下:

select DENSE_RANK() OVER(partition by column order by [UserId]) as den_rank,* from [Order]

需要注意的是:

  • over()函数中的partition by表示排名基于根据column的分区,省略partition by代表当前排名的结果集分区是以整个表进行的 ;
  • over子句中的order by子句与SQL语句中的order by子句没有任何关系(也区分DESC和ASC);
  • over子句中的order by 要与Sql排序记录中的order by 保持一致,否则得到的序号可能不是连续的。

下面通过两个最近刷到的LC数据库习题来进行DENSE_RANK函数的讲解。

2、eg.1-第N高的薪水

编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。

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

例如上述 Employee 表,n = 2 时,应返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查询应返回 null

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200                    |
+------------------------+

比较直观的一种方法,直接单表查询后使用limit N,1获取答案:

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    SET N := N-1;
  RETURN (
      # Write your MySQL query statement below.
      SELECT 
            salary
      FROM 
            employee
      GROUP BY 
            salary
      ORDER BY 
            salary DESC
      LIMIT N, 1
  );
END

而我们通过题目分析可以知道,第二高的薪水可能不存在,也可能是多个,所以直接利用dense_rank函数排序字段值序号连续的特点,通过Salary降序的方式进行查询:

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  RETURN (
      # Write your MySQL query statement below.
      select
        distinct Salary
      from
            (select
             	# 按Salary降序(DESC)排列,再通过where筛选number为N的列,最后distinct拿到salary
                Salary, DENSE_RANK() OVER(order by Salary DESC) as 'number'
            from
                Employee) t
      where number=N
  );
END

3、eg.2-部门工资前三高的所有员工

Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentId

+----+-------+--------+--------------+
| Id | Name  | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1  | Joe   | 85000  | 1            |
| 2  | Henry | 80000  | 2            |
| 3  | Sam   | 60000  | 2            |
| 4  | Max   | 90000  | 1            |
| 5  | Janet | 69000  | 1            |
| 6  | Randy | 85000  | 1            |
| 7  | Will  | 70000  | 1            |
+----+-------+--------+--------------+

Department 表包含公司所有部门的信息。

+----+----------+
| Id | Name     |
+----+----------+
| 1  | IT       |
| 2  | Sales    |
+----+----------+

编写一个 SQL 查询,找出每个部门获得前三高工资的所有员工。例如,根据上述给定的表,查询结果应返回:

+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT         | Max      | 90000  |
| IT         | Randy    | 85000  |
| IT         | Joe      | 85000  |
| IT         | Will     | 70000  |
| Sales      | Henry    | 80000  |
| Sales      | Sam      | 60000  |
+------------+----------+--------+

解释:

IT 部门中,Max 获得了最高的工资,Randy 和 Joe 都拿到了第二高的工资,Will 的工资排第三。销售部门(Sales)只有两名员工,Henry 的工资最高,Sam 的工资排第二。

先上我的答案:

# Write your MySQL query statement below
select d.name 'Department', t.Name 'Employee', t.Salary
from
(select Name, DepartmentId, Salary,
    DENSE_RANK() over(partition by DepartmentId order by Salary DESC) as 's_rank'
from Employee) t
JOIN Department d
ON d.Id=t.DepartmentId
where t.s_rank IN(1,2,3)

一步一步地进行分析:

  • 先看结果集里要求的列有哪些,我们可以看到包括Employee 表的Name列、Salary列以及Department 表的Name列;

  • 也就是说,我们可以先求出Employee 表的Name、Salary、DepartmentId再通过JOINDepartment 表来获取部门名称;

  • 对于Employee 表,我们获取每个部门的Salary降序排名:

    • # 根据DepartmentId分组,每个分组又通过Salary的降序排列,最后别名为s_rank
      select Name, DepartmentId, Salary,
          DENSE_RANK() over(partition by DepartmentId order by Salary DESC) as 's_rank'
      from Employee
      
  • 上述查询结果作为临时表t和Department做连接查询,使用where限制排名为1或2或3;

    • (select Name, DepartmentId, Salary,
          DENSE_RANK() over(partition by DepartmentId order by Salary DESC) as 's_rank'
      from Employee) t
      JOIN Department d
      ON d.Id=t.DepartmentId
      
      where t.s_rank IN(1,2,3)
      

4、补充介绍-over()函数:

over函数的写法:

假设有一张表grade(id, name, score, class)

# 按照class进行分区
over(partition by class)
# 按照score进行累计
over(order by score)
# 按照class分区进行成绩累计
over(partition by class order by score)

over()中使用了order by子句,所以默认从第一行累计到当前行!!!;若不使用order by子句,则会针对整个分区求和(此处没指定partition by的话,将整个表视为一个分区,指定partition by就将该分区求和)

与over()函数结合使用的函数:

分析函数over()用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行。

  • rank()和dense_rank()等排名函数+over();

  • sum()+over();

    • #按照b列排序,将a依次相加
      sum(a) over (order by b)
      
  • first_value() over()和last_value() over();

  • count()+over();

    • # 统计按user_id 分类的id个数
      count(id) over(partition by user_id)
      

🎁🎁🎁

第一次写博客呀,之前不管刷题还是看技术的东西都是本地记录,还是决定整理出来,有一个再次思考的过程,并且感觉更有动力😬。

我理解的难免有错误,提前感谢批评指正!希望大家一起进步,把学习当作乐趣!

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-28 00:10:17  更:2021-09-28 00:10:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 14:33:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码