zoukankan      html  css  js  c++  java
  • Hive中row_number()、dense_rank()、rank()的区别

    摘要

    本文对Hive中常用的三个排序函数row_number()dense_rank()rank()的特性进行类比和总结,并通过笔者亲自动手写的一个小实验,直观展现这三个函数的特点。

    三个排序函数的共同点与区别

    函数 共同点 不同点
    row_number() 用于特定场景下实现排序需求;
    均从1开始排序
    无重复排名(相同排名的按序排名)
    dense_rank() 有相同排名,但不会跳过占用的排名
    rank() 有相同排名,但会跳过占用的排名

    实验示例

    set mapreduce.job.queuename=QueueA;
    
    use STUDENT_DB;
    
    --创建学生分数表
    DROP TABLE IF EXISTS STUDENT_DB.SCORE_TABLE1;
    CREATE TABLE IF NOT EXISTS STUDENT_DB.SCORE_TABLE1
    (
        ID          STRING COMMENT '唯一ID',
        NAME        STRING COMMENT '姓名',
        SCORE       INT    COMMENT '分数',
        CLASS_NUM   STRING COMMENT '班级编号'
    )
    COMMENT '学生分数表'
    PARTITIONED BY (pt_dt STRING)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '27'
    STORED AS ORCFILE;
    
    --向学生分数表插入数据
    INSERT OVERWRITE TABLE STUDENT_DB.SCORE_TABLE1 PARTITION(pt_dt='2019-12-12') VALUES
    ('1', '小明', 89, '1班'),
    ('2', '小红', 90, '1班'),
    ('3', '小军', 90, '1班'),
    ('4', '小胖', 91, '1班'),
    ('5', '小李', 87, '1班'),
    ('6', '小郭', 99, '1班');
    
    --创建学生分数排序结果表
    DROP TABLE IF EXISTS STUDENT_DB.SCORE_RANK_TABLE1;
    CREATE TABLE IF NOT EXISTS STUDENT_DB.SCORE_RANK_TABLE1
    (
        ID          STRING COMMENT '唯一ID',
        NAME        STRING COMMENT '姓名',
        SCORE       INT    COMMENT '分数',
        CLASS_NUM   STRING COMMENT '班级编号',
        ROW_NUMBERS STRING COMMENT 'ROW_NUMBER排序结果',
        DENSE_RANKS STRING COMMENT 'DENSE_RANKS排序结果',
        RANKS       STRING COMMENT 'RANKS排序结果'
    )
    COMMENT '学生分数排序结果表'
    PARTITIONED BY (pt_dt STRING)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '27'
    STORED AS ORCFILE;
    
    INSERT OVERWRITE TABLE STUDENT_DB.SCORE_RANK_TABLE1 PARTITION(pt_dt='2019-12-12')
    SELECT ID,
           NAME,
           SCORE,
           CLASS_NUM,
           ROW_NUMBER() OVER(PARTITION BY CLASS_NUM ORDER BY SCORE DESC) AS ROW_NUMBERS,
           DENSE_RANK() OVER(PARTITION BY CLASS_NUM ORDER BY SCORE DESC) AS DENSE_RANKS,
           RANK() OVER(PARTITION BY CLASS_NUM ORDER BY SCORE DESC) AS RANKS
    FROM STUDENT_DB.SCORE_RANK_TABLE1
    WHERE pt_dt='2019-12-12';
    
    SELECT ID,
           NAME,
           SCORE,
           CLASS_NUM,
           ROW_NUMBERS,
           DENSE_RANKS,
           RANKS,
           pt_dt
    FROM STUDENT_DB.SCORE_RANK_TABLE1
    WHERE pt_dt='2019-12-12';
    

    实验结果

    SCORE_RANK_TABLE1

    ID NAME SCORE CLASS_NUM ROW_NUMBERS DENSE_RANKS RANKS pt_dtpt_dt
    6 小郭 99 1班 1 1 1 2019-12-12
    4 小胖 91 1班 2 2 2 2019-12-12
    3 小军 90 1班 3 3 3 2019-12-12
    2 小红 90 1班 4 3 3 2019-12-12
    1 小明 89 1班 5 4 5 2019-12-12
    5 小李 87 1班 6 5 6 2019-12-12

    如上表所示,1班的小军和小红分数均为90,当我们使用ROW_NUMBERS()进行排序时,他们的排名不会并列,而是分别有一个排名。

    当我们使用DENSE_RANK()进行排序时,他们的排名会并列,且后续记录的排名会以当前并列排名为基础+1,即不会跳过被占用的位置。

    当我们使用RANK()进行排名时,他们的排名会并列,且后续记录的排名会跳过被占用的排名数,而不会顺延下去。

    总结

    在实际开发过程中,可根据场景的需要去选择具体的排序函数。一个较为常见的场景是根据某个字段partition by之后在该范围内order by进行排序,然后取首条记录,这时候row_number()基本可以满足需求。

    除此之外,排序函数均较耗性能,特别是如果对大数据量进行全局排序时,一定要考虑性能问题,非必要情况下,避免对大数据量进行全局排序。

  • 相关阅读:
    Linux入门之常用命令(14) kill
    【JVM命令系列】jstack
    【JVM命令系列】javap
    【JVM命令系列】jmap
    Hadoop安全(2)——————UserGroupInformation
    Hadoop安全(1)——————美团Hadoop安全实践
    软件测试流程进阶----两年软件测试总结
    每个程序员应该阅读的10本书籍
    成为优秀程序员的黄金10条法则
    Java异常的深入研究与分析
  • 原文地址:https://www.cnblogs.com/JasonCeng/p/13087894.html
Copyright © 2011-2022 走看看