Spark SQL 之开窗函数

目录

 

一:开窗函数

二:row_number()开窗函数实战

三:开窗函数与一般函数使用的区别?


一:开窗函数


开窗函数的由来:
在开窗函数出现之前存在着非常多用 SQL 语句非常难解决的问题,非常多都要通过复杂的相关子查询或者存储过程来完毕。为了解决这些问题,在2003年ISO  SQL标准增加了开窗函数,开窗函数的使用使得这些经典的难题能够被轻松的解决。眼下在 MSSQLServer、Oracle、DB2 等主流数据库中都提供了对开窗函数的支持

作用:
开窗函数(OVER子句)用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列

窗口函数与普通聚合函数的区别:
与 聚 合函数一样,开窗函数也是对行集组进行聚合计算,可是它不像普通聚合函数那样
每组仅仅返回一个值,开窗函数能够为每组返回多个值,由于开窗函数所运行聚合计算的行集组是窗体

聚合:
SELECT FCITY , FAGE ,  

  SELECT COUNT(* ) FROM T_Person 
  WHERE FSALARY<5000 

FROM T_Person 

开窗
SELECT FCITY , FAGE , COUNT(*) OVER() FROM T_Person 

优势:简化书写与代码读取

二:row_number()开窗函数实战


文本:

Thin Cell Phone 6000
Normal Tablet 1500
Mini Tablet 5500
UltraThin Cell Phone 5000
VeryThin Cell Phone 6000
Big Tablet 2500
Bedable Cell Phone 3000
Foldable Cell Phone 3500
Pro Tablet 4500
Pro2 Tablet 6500

代码:

public static void main(String[] args) {
        SparkConf conf = new SparkConf()
                .setAppName("RowNumberWindowFunction");
        JavaSparkContext sc = new JavaSparkContext(conf);
        HiveContext hiveContext = new HiveContext(sc.sc());
        
        // 创建销售额表,sales表
        hiveContext.sql("DROP TABLE IF EXISTS sales");
        hiveContext.sql("CREATE TABLE IF NOT EXISTS sales ("
                + "product STRING,"
                + "category STRING,"
                + "revenue BIGINT)");  
        hiveContext.sql("LOAD DATA "
                + "LOCAL INPATH '/usr/local/spark-study/resources/sales.txt' "
                + "INTO TABLE sales");
        
        // 开始编写我们的统计逻辑,使用row_number()开窗函数
        // 先说明一下,row_number()开窗函数的作用
        // 其实,就是给每个分组的数据,按照其排序顺序,打上一个分组内的行号
        // 比如说,有一个分组date=20151001,里面有3条数据,1122,1121,1124,
        // 那么对这个分组的每一行使用row_number()开窗函数以后,三行,依次会获得一个组内的行号
        // 行号从1开始递增,比如1122 1,1121 2,1124 3
        
        DataFrame top3SalesDF = hiveContext.sql(""
                + "SELECT product,category,revenue "
                + "FROM ("
                    + "SELECT "
                        + "product,"
                        + "category,"
                        + "revenue,"
                        // row_number()开窗函数的语法说明
                        // 首先可以,在SELECT查询时,使用row_number()函数
                        // 其次,row_number()函数后面先跟上OVER关键字
                        // 然后括号中,是PARTITION BY,也就是说根据哪个字段进行分组
                        // 其次是可以用ORDER BY进行组内排序
                        // 然后row_number()就可以给每个组内的行,一个组内行号
                        + "row_number() OVER (PARTITION BY category ORDER BY revenue DESC) rank "
                    + "FROM sales "  
                + ") tmp_sales "
                + "WHERE rank<=3");
        
        // 将每组排名前3的数据,保存到一个表中
        hiveContext.sql("DROP TABLE IF EXISTS top3_sales");  
        top3SalesDF.saveAsTable("top3_sales");  
        
        sc.close();
    }


    


三:开窗函数与一般函数使用的区别?


DataFrame userAccessLogRowDF;
userAccessLogRowDF.groupBy("date")
        .agg('date, countDistinct('userid))
        
在hql函数中使用? 
hiveContext.sql(""
                + "SELECT product,category,revenue "
                + "FROM ("
                    + "SELECT "
                        + "product,"
                        + "category,"
                        + "revenue,"
                        // row_number()开窗函数的语法说明
                        // 首先可以,在SELECT查询时,使用row_number()函数
                        // 其次,row_number()函数后面先跟上OVER关键字
                        // 然后括号中,是PARTITION BY,也就是说根据哪个字段进行分组
                        // 其次是可以用ORDER BY进行组内排序
                        // 然后row_number()就可以给每个组内的行,一个组内行号
                        + "row_number() OVER (PARTITION BY category ORDER BY revenue DESC) rank "
                    + "FROM sales "  
                + ") tmp_sales "
                + "WHERE rank<=3");

遗留:本质上亦可以使用 DataFrame 调用,只是将sql的语法块儿在DataFrame用方法的形式展示而已?

你可能感兴趣的:(#,Spark,SQL,开窗函数)