精华内容
下载资源
问答
  • 要注意窗口函数和聚合函数有着本质上的区别:聚合函数的最大的特点就是只能操作分组的字段,但是开窗函数可以操作所有的字段,并不受分区字段的限制 对sparkSql窗口函数的理解: 例子: def test

    什么是窗口函数:

    窗口函数解决了哪些问题:

    假如有很多种不同类型的数据,如果我们想按照某个列进行分组,然后在对分组后的数据进行排序,在输出分组排序后的结果,那么依靠普通的函数是无法做到的,那么就应运而生了窗口函数,作用就是:先对数据分组,在对分组后的数据进行排序之类的操作,最后再把想要查询的列的结果查询出来。要注意窗口函数和聚合函数有着本质上的区别:聚合函数的最大的特点就是只能操作分组的字段,但是开窗函数可以操作所有的字段,并不受分区字段的限制

    对sparkSql窗口函数的理解:

    例子:

    def test() = {
        val sparkConf = new SparkConf().setMaster("local[2]")
        val spark = SparkSession.builder().config(sparkConf).getOrCreate()
        val sqlContext = spark.sqlContext
        val data = Array(("lili", "ml", 90),
          ("lucy", "ml", 85),
          ("cherry", "ml", 80),
          ("terry", "ml", 85),
          ("tracy", "cs", 82),
          ("tony", "cs", 86),
          ("tom", "cs", 75))
    
        val schemas = Seq("name", "subject", "score")
        val df = spark.createDataFrame(data).toDF(schemas: _*)
        df.createOrReplaceTempView("person_subject_score")
    
        val sqltext = "select name, subject, score, rank() over (partition by subject order by score desc) as rank from person_subject_score";
        val ret = sqlContext.sql(sqltext)
        ret.show()
      }
    

    执行结果:

    	+------+-------+-----+----+
    	|  name|subject|score|rank|
    	+------+-------+-----+----+
    	|  tony|     cs|   86|   1|
    	| tracy|     cs|   82|   2|
    	|   tom|     cs|   75|   3|
    	|  lili|     ml|   90|   1|
    	|  lucy|     ml|   85|   2|
    	| terry|     ml|   85|   2|
    	|cherry|     ml|   80|   4|
    	+------+-------+-----+----+
    

    窗口函数执行流程的理解:

    //一定要知道,窗口函数的执行,是先分组,后排序,最后查询
    select name, subject, score, rank() over (partition by subject order by score desc) as rank from person_subject_score
    
    //不要被代码的书写顺序欺骗了,在SQL中代码的书写顺序和执行顺序并不是一样的。
    //有开窗函数的SQL怎么执行: 
       //1.首先我们要知道,rank() 是一个窗口函数,但是底层是不知道rank()是不是窗口函数的,那么我们就需要加    //上一个 字段 来告底层,我这个rank()是窗口函数,这个字段就是 over()
       //2.over() 字段的括号中的内容的执行顺序:
       //首先我们要知道的是:我们使用窗口函数无非就是想分组,然后对分组后的数据进行对应的操作,所以我们应该执    //行的操作就是先分组,根据什么字段进行分组
       //分组完成后,剩下的一般就是一些排序的操作 ,根据什么字段进行排序
       //3.分组 排序 执行完毕之后,那么剩下的就是查询操作了。想要查询哪些列,最后在写上我们要查询的字段来自        哪个表格
    

    窗口函数的更加细致的划分:

    over表示这是个窗口函数
    partition by对应的就是分组,即按照什么列分组
    order by对应的是排序,按什么列排序
    
    spark中的window_func包括下面三类:
    1.排名函数(ranking function) 包括rank,dense_rank, row_number,percent_rank, ntile等,后面我们结合例子来看。
    2.分析函数 (analytic functions) 包括cume_dist,lag等。
    3.聚合函数(aggregate functions),就是我们常用的max, min, sum, avg等。
    

    三个常用的排序的开窗函数的特点:

    rank() : 如果相同,则并列,但序号上不连续

    row_number() : 如果相同,则依然顺序递增

    dense_rank() : 如果相同,则并列,但是序号上依然连续

    具体区别看下文


    +------+-------+-----+----+
    |  name|subject|score|rank|
    +------+-------+-----+----+
    |  tony|     cs|   86|   1|
    | tracy|     cs|   82|   2|
    |   tom|     cs|   75|   3|
    |  lili|     ml|   90|   1|
    |  lucy|     ml|   85|   2|
    | terry|     ml|   85|   2|
    |cherry|     ml|   80|   4|
    +------+-------+-----+----+
    
    +------+-------+-----+----------+
    |  name|subject|score|row_number|
    +------+-------+-----+----------+
    |  tony|     cs|   86|         1|
    | tracy|     cs|   82|         2|
    |   tom|     cs|   75|         3|
    |  lili|     ml|   90|         1|
    |  lucy|     ml|   85|         2|
    | terry|     ml|   85|         3|
    |cherry|     ml|   80|         4|
    +------+-------+-----+----------+
    
    +------+-------+-----+----------+
    |  name|subject|score|dense_rank|
    +------+-------+-----+----------+
    |  tony|     cs|   86|         1|
    | tracy|     cs|   82|         2|
    |   tom|     cs|   75|         3|
    |  lili|     ml|   90|         1|
    |  lucy|     ml|   85|         2|
    | terry|     ml|   85|         2|
    |cherry|     ml|   80|         3|
    +------+-------+-----+----------+
    

    cume_dist 开窗函数:

    下面再看个实例,我们想查看某个人在该专业的分位数,该怎么办?
    这个时候就可以用到cume_dist函数了。
    该函数的计算方式为:组内小于等于当前行值的行数/组内总行数

    还是看代码:
    select
    name,
    subject,
    score,
    cume_dist() over (partition by subject order by score desc) as cumedist
    from person_subject_score

    执行结果:
       +------+-------+-----+------------------+
    |  name|subject|score|          cumedist|
    +------+-------+-----+------------------+
    |  tony|     cs|   86|0.3333333333333333|
    | tracy|     cs|   82|0.6666666666666666|
    |   tom|     cs|   75|               1.0|
    |  lili|     ml|   90|              0.25|
    |  lucy|     ml|   85|              0.75|
    | terry|     ml|   85|              0.75|
    |cherry|     ml|   80|               1.0|
    +------+-------+-----+------------------+
    
    展开全文
  • 如何查看Dll中包含了哪些函数

    千次阅读 2020-04-05 13:20:49
    如何查看Dlll包含了哪些函数两种方法: 1. 用工具depends来查看 该工具可从http://www.dependencywalker.com/下载,打开该软件,再通过该软件打开需要查看的Dll,比如打开C运行时库,C:\Windows\System32\...

    如何查看Dlll包含了哪些函数,有两种方法:

    1. 用工具depends来查看

    该工具可从http://www.dependencywalker.com/下载,打开该软件,再通过该软件打开需要查看的Dll, 比如打开C运行时库,C:\Windows\System32\msvcrt.dll,呈现如下:

    在窗中右侧中部,看到了我们熟悉的C语言标准库函数fopen.

    2.利用dumpbin来查看

    dumpbin位于VC的安装路径下,比如C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin。
    点击: 开始菜单->运行,输入CMD, 进入命令行运行窗口,输入 CD C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin, 将目录切换到dumpbin所在目录,再输入dumpbin /exports C:\Windows\System32\msvcrt.dll命令即可查看Dll中的函数。

    查看的结果如下:

    也可以在命令中加入 > 将结果输出到一个文件中,如下,则最后的结果将输出到D盘的msvcrt.txt文件中。

    展开全文
  • 作者: Kim Berg ...我有一张表,登记着我在哪些日期手机漫游(漫游的意思是我在国外)。我还有一个视图,生成了特定期间的所有日期: create table plch_roaming (  roam_date date primary key ) / inser
    作者:        Kim Berg Hansen  

    运行环境:SQLPLUS, SERVEROUTPUT已打开


    我有一张表,登记着我在哪些日期有手机漫游(漫游的意思是我在国外)。我还有一个视图,生成了特定期间的所有日期:

    create table plch_roaming (
       roam_date   date primary key
    )
    /

    insert into plch_roaming values (date '2016-01-03')
    /
    insert into plch_roaming values (date '2016-01-04')
    /
    insert into plch_roaming values (date '2016-01-05')
    /
    insert into plch_roaming values (date '2016-01-06')
    /
    insert into plch_roaming values (date '2016-01-09')
    /
    insert into plch_roaming values (date '2016-01-10')
    /
    insert into plch_roaming values (date '2016-01-11')
    /
    insert into plch_roaming values (date '2016-01-12')
    /
    insert into plch_roaming values (date '2016-01-14')
    /
    commit
    /

    create view plch_calendar as
    select date '2016-01-01' + level - 1 as calendar_date
      from dual
    connect by level <= 14
    /

    我的手机费是统一费率(相当于包月),当我在漫游也是如此。但仅仅是在漫游不太多的时候。 规则如下:

    当我不在漫游(我在国内),通话包含在统一费率中。
    当我在漫游时,如果我之前四天中漫游不多于两天,则通话仍然包含在统一费率中。

    当我在漫游时,如果我之前四天中漫游多于两天,则在统一费率之上有附加费。

    例如,一月份的前几天我不在漫游,那些天是统一费率的。1月3号我在漫游,但是之前的四天没有一天是在漫游,所以它仍然是统一费率。在1月4号,之前的四天中有一天漫游,所以1月4号仍然是统一费率。1月5号是统一费率,因为前四天之中有两天是在漫游。但是1月6号要收费,因为之前的四天中有三天在漫游。

    对于一月份的前14天(日期由上述视图生成),我想要一个清单,每天显示我的所在地(在家(Home)或者漫游(Roaming)), 以及当天的通话是包含在统一费率(Flat)或者是要额外收费(Fee)。

    哪些选项包含了一个查询能够给我这样的一个清单:

    CALENDAR_D LOCATIO CHAR
    ---------- ------- ----
    2016-01-01 Home    Flat
    2016-01-02 Home    Flat
    2016-01-03 Roaming Flat
    2016-01-04 Roaming Flat
    2016-01-05 Roaming Flat
    2016-01-06 Roaming Fee
    2016-01-07 Home    Flat
    2016-01-08 Home    Flat
    2016-01-09 Roaming Flat
    2016-01-10 Roaming Flat
    2016-01-11 Roaming Flat
    2016-01-12 Roaming Fee
    2016-01-13 Home    Flat
    2016-01-14 Roaming Fee

    (A) 
    select c.calendar_date
         , case
             when r.roam_days is null then 'Home'
             else 'Roaming'
           end as location
         , case
              when r.roam_days > 2 then 'Fee'
              else 'Flat'
           end as charge
      from plch_calendar c
      left outer join (
       select roam_date
            , count(*) over (
                 order by roam_date
                 RANGE between interval '4' day preceding
                           and interval '1' day preceding
              ) as roam_days
         from plch_roaming
      ) r
       on r.roam_date = c.calendar_date
    order by c.calendar_date
    /

    (B) 
    select c.calendar_date
         , case
             when r.roam_days is null then 'Home'
             else 'Roaming'
           end as location
         , case
              when r.roam_days > 2 then 'Fee'
              else 'Flat'
           end as charge
      from plch_calendar c
      left outer join (
       select roam_date
            , count(*) over (
                 order by roam_date
                 ROWS between interval '4' day preceding
                           and interval '1' day preceding
              ) as roam_days
         from plch_roaming
      ) r
       on r.roam_date = c.calendar_date
    order by c.calendar_date
    /

    (C) 
    select c.calendar_date
         , case
             when r.roam_days is null then 'Home'
             else 'Roaming'
           end as location
         , case
              when r.roam_days > 2 then 'Fee'
              else 'Flat'
           end as charge
      from plch_calendar c
      left outer join (
       select roam_date
            , count(*) over (
                 order by roam_date
                 ROWS between 4 preceding and 1 preceding
              ) as roam_days
         from plch_roaming
      ) r
       on r.roam_date = c.calendar_date
    order by c.calendar_date
    /


    (D) 
    select calendar_date
         , case
             when roam_date is null then 'Home'
             else 'Roaming'
           end as location
         , case
              when roam_date is not null and roam_days > 2 then 'Fee'
              else 'Flat'
           end as charge
      from (
       select c.calendar_date
            , r.roam_date
            , count(r.roam_date) over (
                 order by c.calendar_date
                 RANGE between interval '4' day preceding
                           and interval '1' day preceding
              ) as roam_days
         from plch_calendar c
         left outer join plch_roaming r
          on r.roam_date = c.calendar_date
      )
    order by calendar_date
    /

    (E) 
    select calendar_date
         , case
             when roam_date is null then 'Home'
             else 'Roaming'
           end as location
         , case
              when roam_date is not null and roam_days > 2 then 'Fee'
              else 'Flat'
           end as charge
      from (
       select c.calendar_date
            , r.roam_date
            , count(r.roam_date) over (
                 order by c.calendar_date
                 ROWS between 4 preceding and 1 preceding
              ) as roam_days
         from plch_calendar c
         left outer join plch_roaming r
          on r.roam_date = c.calendar_date
      )
    order by calendar_date

    /




    本题考查分析函数中over()用法
    开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
    over(order by salary)按照salary排序进行累计,orderby是个默认的开窗函数
    over(partition by deptno)按照部门分区
    over(order by salary range between 50 preceding and 150 following)
    每行对应的数据窗口是之前行幅度值不超过50,之后行幅度值不超过150
    over(order by salary rows between 50 preceding and 150 following)
    每行对应的数据窗口是之前50行,之后150行
    over(order by salary rows between unboundedpreceding and unbounded following)
    每行对应的数据窗口是从第一行到最后一行,等效:
    over(order by salary range between unboundedpreceding and unbounded following)

    本题关键

      left outer join (
       select roam_date
            , count(*) over (
                 order by roam_date
                 RANGE between interval '4' day preceding
                           and interval '1' day preceding
              ) as roam_days
         from plch_roaming
      ) r

    over (
                 order by roam_date
                 RANGE between interval '4' day preceding
                           and interval '1' day preceding
              )

       select c.calendar_date
            , r.roam_date
            , count(r.roam_date) over (
                 order by c.calendar_date
                 ROWS between 4 preceding and 1 preceding
              ) as roam_days
         from plch_calendar c
         left outer join plch_roaming r
          on r.roam_date = c.calendar_date

    over (
                 order by c.calendar_date
                 ROWS between 4 preceding and 1 preceding
              ) 


    答案 A D E
    B:错误,数据类型不一致,rows是按物理位置排序
    C:错误,因为rows是按物理位置排序,导致从第3个roam_days开始都是大于2
    E:正确,进行左连接后非漫游时roam_date是空值,count(r.roam_date)不会计算空值


    展开全文
  • GetLogicalDrives 判断系统中存在哪些逻辑驱动器字母 GetLogicalDriveStrings 获取一个字串,其中包含了当前所有逻辑驱动器的根驱动器路径 GetOverlappedResult 判断一个重叠操作当前的状态 GetPrivateProfileInt...
  • 哪些函数是文档、视图相互处理用的◆ 23 ◆如何建立一个基于对话框一程序◆ 23 ◆如何建立一个线程◆ 24 ◆如何让窗口产生一个图标(从应用程序资源中取出)◆ 24 ◆如何得到一个edit的录入的值◆ 24 ◆如何启动...
  • HIVE

    2021-05-23 18:20:50
    一、hive架构相关 ... 5.4、窗口函数(开窗函数) 六、UDF、UDAF、UDTF相关面试题 6.1、UDF、UDAF、UDTF的区别? 6.2、怎么自定义UDF、UDAF、UDTF函数? ...

     

    一、hive架构相关

    Hive的构成包括哪些部分?

    用户接口层:常用的三个分别是CLI,JDBC/ODBC 和 WUI。其中最常用的是CLI,CLI启动的时候,会同时启动一个Hive副本。JDBC/ODBC是Hive的客户端,用户通过客户端连接至Hive Server。在启动客户端模式的时候,需要指出Hive Server所在节点,并且在该节点启动Hive Server。WUI是通过浏览器访问Hive。
    元数据存储:Hive将元数据存储在RDBMS中,有三种模式可以连接到数据库,分别是内嵌式元存储服务器、本地元存储服务器、远程元存储服务器。
    Driver(Compiler/Optimizer/Executor)

    Driver完成HQL查询语句的词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS上,并由MapReduce调用执行。

     

     

    二、hive的特点

    本题主要为了考察对hive的整体使用场景的掌握程度,毕竟只有知道了hive的特点,才能有针对性的在实际项目中的合适场景下使用hive。

    可以从下面四个角度去分析:

    1. 数据存储位置

      Hive的数据存储在hdfs上元数据可以存储在指定的地方比如mysql,PostgreSQL等。

        Hive支持三种不同的元存储服务器,分别为:内嵌式元存储服务器、本地元存储服务器、远程元存储服务器,每种存储方式使用不同的配置参数。

        内嵌式元存储主要用于单元测试,在该模式下每次只有一个进程可以连接到元存储,Derby是内嵌式元存储的默认数据库。

        在本地模式下,每个Hive客户端都会打开到数据存储的连接并在该连接上请求SQL查询。

        在远程模式下,所有的Hive客户端都将打开一个到元数据服务器的连接,该服务器依次查询元数据,元数据服务器和客户端之间使用Thrift协议通信。
     

    1. 数据更新

      Hive处理数据时一般不对数据进行改写,因为它不支持行级别的增删操作,如果要进行更新数据,一般可以通过分区或者表直接覆盖。

    2. 执行效率

      Hive 执行延迟较高。虽然在小数据量时传统数据库延迟更低,但是当数据规模大到超过传统数据库的处理能力的时候,Hive 的并行计算显然能体现出优势。

    3. 数据规模

      Hive 支持大规模的数据计算,通常是PB级别的数据。

    三、数据组织

     


       数据组织主要考察面试者对Hive的数据库、表、视图、分区和表数据的概念的考察,清楚的说出每个概念的含义就可以了。

    1)HIve的存储结构包括哪些?可以具体说说每种结构吗?

       包括数据库、表、分区、桶、视图和表数据。

    database-数据库在 HDFS 中表现为指定的目录下的一个文件夹,通过${hive.metastore.warehouse.dir}可以进行设置;

    table-内部表在 HDFS 中表现为某个 database 目录下一个文件夹,默认创建的都是内部表;

    external table-外部表与内部表类似,在 HDFS 中表现为指定目录下一个文件夹;

    bucket-桶在 HDFS 中表现为同一个表目录或者分区目录下根据某个字段的值进行 hash 散列之后的多个文件;

    view-视图与表类似,只读,基于基本表创建,不占存储空间,实际是一连串的查询语句;

    表数据对应 HDFS 对应目录下的文件。

     

    Hive表有受控表(内部表)、外部表、分区表、桶表四种。

    内部表,就是一般的表,前面讲到的表都是内布标,当表定义被删除的时候,表中的数据随之一并被删除。

    外部表,数据存在与否和表的定义互不约束,仅仅只是表对hdfs上相应文件的一个引用,当删除表定义的时候,表中的数据依然存在。

    创建外部表, external是外部表的关键字,也是和内部表有区别的地方
    create external table tblName(colName colType...);
    加载数据
    alter table tblName set location 'hdfs_absolute_uri';

    外部表还可以在创建表的时候指定数据的位置,引用当前位置的数据。
    create external table tblName(colName colType...) location 'hdfs_absolute_uri';

    内部表和外部表的转换:
    内——>外
    alter table tblName set tblproperties('EXTERNAL'='TRUE');
    外——>内
    alter table tblName set tblproperties('EXTERNAL'='FALSE');

    分区表
    如何创建一张分区表?只需要在之前的创建表后面使用partition by加上分区字段就可以了,eg.
      create table tblName (
       id int comment 'ID',
       name string comment 'name' 
      ) partitioned by (dt date comment 'create time')
      row format delimited
      fields terminated by '\t';

    如何加载数据?
    load data local inpath linux_fs_path into table tblName partition(dt='2015-12-12');

    分区的一些操作:
    查询分区中的数据:select * from tblName where dt='2015-12-13';(分区相当于where的一个条件)
    手动创建一个分区:alter table tblName add partition(dt='2015-12-13');
    查看分区表有哪些分区:show partitions tblName;
    删除一个分区(数据一起删掉了):alter table tblName drop partition(dt='2015-12-12');

    多个分区如何创建?
    和单分区表的创建类似:
      create table tblName (
       id int comment 'ID',
       name string comment 'name' 
      ) partitioned by (year int comment 'admission year', school string comment 'school name')
      row format delimited
      fields terminated by '\t';

    同时也可以从hdfs上引用数据:
    alter table tblName partition(year='2015', school='crxy') set location hdfs_uri;
    注意:
    必须得现有分区,必须要使用hdfs绝对路径。

    桶表
    桶表是对数据进行哈希取值,然后放到不同文件中存储。查看每个桶文件中的内容,可以看出是通过对 buckets 取模确定的。
    如何创建桶表?
    create table tblName_bucket(id int) clustered by (id) into 3 buckets;
    说明:
    clustered by :按照什么分桶
    into x buckets:分成x个桶
    如何加载数据?
    不能使用load data这种方式,需要从别的表来引用
    insert into table tblName_bucket select * from tbl_other;
    注意:在插入数据之前需要先设置开启桶操作,不然插入数据不会设置为桶!
    set hive.enforce.bucketing=true;
    桶表的主要作用:
    数据抽样
    提高某些查询效率
    注意:
    需要特别注意的是:clustered by 和 sorted by 不会影响数据的导入,这意味着,用户必须自己负责数据如何导入,包括数据的分桶和排序。
    'set hive.enforce.bucketing = true'可以自动控制上一轮 reduce 的数量从而适配 bucket 的个数,
    当然,用户也可以自主设置 mapred.reduce.tasks 去适配bucket 个数,
    推荐使用'set hive.enforce.bucketing = true'。

     

    • 1)内部表和外部表的区别吗?

       内部表数据由Hive自身管理,外部表数据由HDFS管理;删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除。

     

    • 2)说说分区表和分桶表的区别?

    分区表,Hive 数据表可以根据某些字段进行分区操作,细化数据管理,让部分查询更快,不同分区对应不同的目录;

    分桶表:表和分区也可以进一步被划分为桶,分桶是相对分区进行更细粒度的划分。分桶将整个数据内容按照某列属性值的hash值进行区分,不同的桶对应不同的文件。

     

     

    分区、分桶的作用:

    我们知道在传统的DBMs系统中,一般都具有表分区的功能,通过表分区能够在特定的区域检索数据,减少扫描成本,在一定程度上提高了查询效率,当然我们还可以通过进一步在分区上建立索引,进一步提高查询效率。

    在Hive中的数据仓库中,也有分区分桶的概念,在逻辑上,分区表与未分区表没有区别,在物理上分区表会将数据按照分区间的列值存储在表目录的子目录中,目录名=“分区键=键值”。其中需要注意的是分区键的列值存储在表目录的子目录中,目录名=“分区键=键值”。其中需要注意的是分区键的值不一定要基于表的某一列(字段),它可以指定任意值,只要查询的时候指定相应的分区键来查询即可。我们可以对分区进行添加、删除、重命名、清空等操作。

    分桶则是指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀的分发到各个桶文件中。因为分桶操作需要根据某一列具体数据来进行哈希取模操作,故指定的分桶列必须基于表中的某一列(字段)。分桶改变了数据的存储方式,它会把哈希取模相同或者在某一个区间的数据行放在同一个桶文件中。如此一来便可以提高查询效率。如果我们需要对两张在同一个列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的通进行JOIN操作即可。

    还有一点需要点一下:在hive中的数据是存储在hdfs中的,我们知道hdfs中的数据是不允许修改只能追加的,那么在hive中执行数据修改的命令时,就只能先找到对应的文件,读取后执行修改操作,然后重新写一份文件。如果文件比较大,就需要大量的IO读写。在hive中采用了分桶的策略,只需要找到文件存放对应的桶,然后读取再修改写入即可。

    https://blog.csdn.net/shudaqi2010/article/details/90288901

     

     

     

    五、介绍一下有哪些常用函数?

    5.1、行转列函数

    1. CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串。

      例如: concat( aa, ‘:’, bb) 就相当于把aa列和bb列用冒号连接起来了,aa:bb。

    2. CONCAT_WS(separator, str1, str2,…):CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。但是CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

    3. COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总产生array类型字段。

    5.2、列转行函数

    1. EXPLODE(col):将hive某列中复杂的array或者map结构拆分成多行。

    2. LATERAL VIEW:常和UDTF函数一起使用。

      用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias

      解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

    5.3、Rank排名函数

    1. RANK() 排序相同时会重复,总数不会变;
    2. DENSE_RANK() 排序相同时会重复,总数会减少;
    3. ROW_NUMBER() 根据顺序计算排名。

    在实际开发中,以上三个rank函数通常是和开窗函数一起使用的。

    5.4、窗口函数(开窗函数)

    1. OVER():用于指定分析函数工作时的数据窗口大小,这个数据窗口大小可能会随着行的变而变化;

    2. CURRENT ROW:当前行;

    3. n PRECEDING:往前n行数据;

    4. n FOLLOWING:往后n行数据;

    5. UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点;

    6. LAG(col,n,default_val):往前第n行数据;

    7. LEAD(col,n, default_val):往后第n行数据;

    8. NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。这个函数需要注意:n必须为int类型。

    六、UDF、UDAF、UDTF相关面试题

    6.1、UDF、UDAF、UDTF的区别?

    当Hive自带的函数无法满足我们的业务处理需求时,hive允许我们自定义函数来满足需求。

    根据自定义函数的类别分为以下三种:

    1. UDF:User-Defined-Function,用户自定义函数,数据是一进一出,功能类似于大多数数学函数或者字符串处理函数;
    2. UDAF:User-Defined Aggregation Function,用户自定义聚合函数,数据是多进一出,功能类似于 count/max/min;
    3. UDTF:User-Defined Table-Generating Functions,用户自定义表生成函数,数据是一进多处,功能类似于lateral view explore();

    6.2、怎么自定义UDF、UDAF、UDTF函数?

    1. 自定义UDF函数

      • 继承org.apache.hadoop.hive.ql.UDF函数;
      • 重写evaluate方法,evaluate方法支持重载。
    2. 自定义UDAF函数

      • 必须继承org.apache.hadoop.hive.ql.exec.UDAF(函数类继承)和org.apache.hadoop.hive.ql.exec.UDAFEvaluator(内部类Evaluator实现UDAFEvaluator接口);

      • 重写Evaluator方法时需要实现 init、iterate、terminatePartial、merge、terminate这几个函数:

        init():类似于构造函数,用于UDAF的初始化

        iterate():接收传入的参数,并进行内部的轮转,返回boolean

        terminatePartial():无参数,其为iterate函数轮转结束后,返回轮转数据,类似于hadoop的Combiner

        merge():接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean

        terminate():返回最终的聚集函数结果

    3. 自定义UDTF函数

      • 继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF函数;

      • 重写实现initialize, process, close三个方法。

        1. UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息(返回个数,类型)。

        2. 初始化完成后,会调用process方法,真正的处理过程在process函数中,在process中,每一次forward()调用产生一行;如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward()函数。

        3. 最后close()方法调用,对需要清理的方法进行清理。

    通常使用 UDF 函数解析公共字段;用 UDTF 函数解析事件字段。

    七、hive怎么解决数据倾斜?

    1. group by

      注:group by 优于 distinct group

      情形:group by 维度过小,某值的数量过多

      后果:处理某值的 reduce 非常耗时

      解决方式:采用 sum() group by 的方式来替换 count(distinct)完成计算。

    2. count(distinct)

      情形:某特殊值过多

      后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务

      解决方式:count distinct 时,将值为空的情况单独处理,比如可以直接过滤空值的行,

      在最后结果中加 1。如果还有其他计算,需要进行 group by,可以先将值为空的记录单独处

      理,再和其他计算结果进行 union。

    3. 不同数据类型关联产生数据倾斜

      情形:比如用户表中 user_id 字段为 int,log 表中 user_id 字段既有 string 类型也有 int 类

      型。当按照 user_id 进行两个表的 Join 操作时。

      后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务

      默认的 Hash 操作会按 int 型的 id 来进行分配,这样会导致所有 string 类型 id 的记录都分配

      到一个 Reducer 中。

      解决方式:把数字类型转换成字符串类型

      select * from users a left outer join logs b on a.usr_id = cast(b.user_id as string)
      • 1
      • 2
      • 3
    4. 开启数据倾斜时负载均衡

      set hive.groupby.skewindata=true;
      
      • 1

      思想:就是先随机分发并处理,再按照 key group by 来分发处理。

      操作:当选项设定为 true,生成的查询计划会有两个 MRJob。

      第一个 MRJob 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 GroupBy Key 有可能被分发到不同的Reduce 中,从而达到负载均衡的目的;

      第二个 MRJob 再根据预处理的数据结果按照 GroupBy Key 分布到 Reduce 中(这个过程可以保证相同的原始 GroupBy Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

      总结:它使计算变成了两个 mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个 key 随机均匀分布到各个reduce 上计算,但是这样只能完成部分计算,因为相同 key 没有分配到相同 reduce 上。所以需要第二次的 mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次 mapreduce 已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次mr 中随机分布到各个节点完成。

    5. 控制空值分布

      将为空的 key 转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个 Reducer。

      注:对于异常值如果不需要的话,最好是提前在 where 条件里过滤掉,这样可以使计算量大大减少。

      实践中,可以使用 case when 对空值赋上随机值。此方法比直接写 is not null 更好,因为前者 job 数为 1,后者为 2.

      使用 case when 实例 1:

      select userid, name from user_info a join ( select case when userid is null then cast (rand(47)* 100000 as int ) else userid end from user_read_log )b on a.userid = b.userid
      •  

      使用 case when 实例 2:

      select '${date}' as thedate, a.search_type, a.query, a.category, a.cat_name, a.brand_id, a.brand_name, a.dir_type, a.rewcatid, a.new_cat_name, a.new_brand_id, f.brand_name as new_brand_name, a.pv, a.uv, a.ipv, a.ipvuv, a.trans_amt, a.trans_num, a.alipay_uv from fdi_search_query_cat_qp_temp a left outer join brand f on f.pt='${date}000000' and case when a.new_brand_id is null then concat('hive',rand() ) else a.new_brand_id end = f.brand_id;
      •  

    如果上述的方法还不能解决,比如当有多个 JOIN 的时候,建议建立临时表,然后拆分HIVE SQL 语句。

    八、hive优化相关面试题

    1. MapJoin

      如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换 成 Common Join,即:在 Reduce 阶段完成 join。容易发生数据倾斜。可以用MapJoin把小 表全部加载到内存在 map 端进行 join,避免 reducer 处理。

    2. 行列过滤

      列处理:在 SELECT 中,只拿需要的列,如果有,尽量使用分区过滤,少用 SELECT *。

      行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在 Where 后面,那 么就会先全表关联,之后再过滤。

    3. 多采用分桶技术

    4. 结合实际环境合理设置 Map 数

      1. 通常情况下,作业会通过 input的目录产生一个或者多个map任务。 主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小;
      2. map数不是越多越好;如果一个任务有很多小文件(远远小于块大小 128m),则每个小文件 也会被当做一个块,用一个 map 任务来完成,而一个 map 任务启动和初始化的时间远远大 于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的 map 数是受限的。解决这个问题需要减少map数。
      3. 并不是每个map处理接近128m的文件块就是完美的;比如有一个 127m 的文件,正常会用一个 map 去完成,但这个文件只 有一个或者两个小字段,却有几千万的记录,如果 map 处理的逻辑比较复杂,用一个 map 任务去做,肯定也比较耗时。解决这个问题需要增加map数。
    5. 合并大量小文件

      在Map执行前合并小文件,可以减少Map数:CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat 没有对小文件合并功能。

    6. 设置合理的Reduce数

      Reduce 个数也并不是越多越好

      1. 过多的启动和初始化 Reduce 也会消耗时间和资源;
      2. 有多少个 Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
      3. 在设置Reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的 Reduce 数;使单个 Reduce 任务处理数据量大小要合适;
    7. 输出合并小文件常用参数

      SET hive.merge.mapfiles = true; -- 默认 true,在 map-only 任务结束时合并小文件 SET hive.merge.mapredfiles = true; -- 默认 false,在 map-reduce 任务结束时合并小文件 SET hive.merge.size.per.task = 268435456; -- 默认 256M SET hive.merge.smallfiles.avgsize = 16777216; -- 当输出文件的平均大小小于 16m 该值时,启动一个独立的 map-reduce 任务进行文件 merge
      • 1
      • 2
      • 3
      • 4
    8. 开启 map 端 combiner(不影响最终业务逻辑)

      开启命令:

      set hive.map.aggr=true;
      • 1
    9. 中间结果压缩

      设置 map 端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了 IO 读写和网络传输,能提高很多效率)

     

     

     

     

    • Hive执行
      • HQL --> Job --> Map/Reduce
      • 执行计划
        • explain [extended] hql
        • 样例
        • select col,count(1) from test2 group by col;
        • explain select col,count(1) from test2 group by col;
    • Hive表优化
      • 分区
        • set hive.exec.dynamic.partition=true;
        • set hive.exec.dynamic.partition.mode=nonstrict;
        • 静态分区
        • 动态分区
      • 分桶
        • set hive.enforce.bucketing=true;
        • set hive.enforce.sorting=true;
      • 数据
        • 相同数据尽量聚集在一起
    • Hive Job优化
      • 并行化执行
        • 每个查询被hive转化成多个阶段,有些阶段关联性不大,则可以并行化执行,减少执行时间
        • set hive.exec.parallel= true;
        • set hive.exec.parallel.thread.numbe=8;
      • 本地化执行
        • job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB)
        • job的map数必须小于参数:hive.exec.mode.local.auto.tasks.max(默认4)
        • job的reduce数必须为0或者1
        • set hive.exec.mode.local.auto=true;
        • 当一个job满足如下条件才能真正使用本地模式:
      • job合并输入小文件
        • set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
        • 合并文件数由mapred.max.split.size限制的大小决定
      • job合并输出小文件
        • set hive.merge.smallfiles.avgsize=256000000;当输出文件平均小于该值,启动新job合并文件
        • set hive.merge.size.per.task=64000000;合并之后的文件大小
      • JVM重利用
        • set mapred.job.reuse.jvm.num.tasks=20;
        • JVM重利用可以使得JOB长时间保留slot,直到作业结束,这在对于有较多任务和较多小文件的任务是非常有意义的,减少执行时间。当然这个值不能设置过大,因为有些作业会有reduce任务,如果reduce任务没有完成,则map任务占用的slot不能释放,其他的作业可能就需要等待。
      • 压缩数据
        • set hive.exec.compress.output=true;
        • set mapred.output.compreession.codec=org.apache.hadoop.io.compress.GzipCodec;
        • set mapred.output.compression.type=BLOCK;
        • set hive.exec.compress.intermediate=true;
        • set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
        • set hive.intermediate.compression.type=BLOCK;
        • 中间压缩就是处理hive查询的多个job之间的数据,对于中间压缩,最好选择一个节省cpu耗时的压缩方式
        • hive查询最终的输出也可以压缩
    • Hive Map优化
      • set mapred.map.tasks =10; 无效
      • (1)默认map个数
        • default_num=total_size/block_size;
      • (2)期望大小
        • goal_num=mapred.map.tasks;
      • (3)设置处理的文件大小
        • split_size=max(mapred.min.split.size,block_size);
        • split_num=total_size/split_size;
      • (4)计算的map个数
        • compute_map_num=min(split_num,max(default_num,goal_num))
      • 经过以上的分析,在设置map个数的时候,可以简答的总结为以下几点:
        • 增大mapred.min.split.size的值
        • 如果想增加map个数,则设置mapred.map.tasks为一个较大的值
        • 如果想减小map个数,则设置mapred.min.split.size为一个较大的值
        • 情况1:输入文件size巨大,但不是小文件
        • 情况2:输入文件数量巨大,且都是小文件,就是单个文件的size小于blockSize。这种情况通过增大mapred.min.split.size不可行,需要使用combineFileInputFormat将多个input path合并成一个InputSplit送给mapper处理,从而减少mapper的数量。
      • map端聚合
        • set hive.map.aggr=true;
      • 推测执行
        • mapred.map.tasks.apeculative.execution
    • Hive Shuffle优化
      • Map端
        • io.sort.mb
        • io.sort.spill.percent
        • min.num.spill.for.combine
        • io.sort.factor
        • io.sort.record.percent
      • Reduce端
        • mapred.reduce.parallel.copies
        • mapred.reduce.copy.backoff
        • io.sort.factor
        • mapred.job.shuffle.input.buffer.percent
        • mapred.job.shuffle.input.buffer.percent
        • mapred.job.shuffle.input.buffer.percent
    • Hive Reduce优化
      • 需要reduce操作的查询
        • group by,join,distribute by,cluster by...
        • order by比较特殊,只需要一个reduce
        • sum,count,distinct...
        • 聚合函数
        • 高级查询
      • 推测执行
        • mapred.reduce.tasks.speculative.execution
        • hive.mapred.reduce.tasks.speculative.execution
      • Reduce优化
        • numRTasks = min[maxReducers,input.size/perReducer]
        • maxReducers=hive.exec.reducers.max
        • perReducer = hive.exec.reducers.bytes.per.reducer
        • hive.exec.reducers.max 默认 :999
        • hive.exec.reducers.bytes.per.reducer 默认:1G
        • set mapred.reduce.tasks=10;直接设置
        • 计算公式
    • Hive查询操作优化
    • join优化
      • 关联操作中有一张表非常小
      • 不等值的链接操作
      • set hive.auto.current.join=true;
      • hive.mapjoin.smalltable.filesize默认值是25mb
      • select /*+mapjoin(A)*/ f.a,f.b from A t join B f on (f.a=t.a)
      • hive.optimize.skewjoin=true;如果是Join过程出现倾斜,应该设置为true
      • set hive.skewjoin.key=100000; 这个是join的键对应的记录条数超过这个值则会进行优化
      • mapjoin
      • 简单总结下,mapjoin的使用场景:
    • Bucket join
      • 两个表以相同方式划分桶
      • 两个表的桶个数是倍数关系
      • crete table order(cid int,price float) clustered by(cid) into 32 buckets;
      • crete table customer(id int,first string) clustered by(id) into 32 buckets;
      • select price from order t join customer s on t.cid=s.id
    • join 优化前
      • select m.cid,u.id from order m join customer u on m.cid=u.id where m.dt='2013-12-12';
    • join优化后
      • select m.cid,u.id from (select cid from order where dt='2013-12-12')m join customer u on m.cid=u.id;
    • group by 优化
      • hive.groupby.skewindata=true;如果是group by 过程出现倾斜 应该设置为true
      • set hive.groupby.mapaggr.checkinterval=100000;--这个是group的键对应的记录条数超过这个值则会进行优化
    • count distinct 优化
      • 优化前
        • select count(distinct id) from tablename
      • 优化后
        • select count(1) from (select distinct id from tablename) tmp;
        • select count(1) from (select id from tablename group by id) tmp;
      • 优化前
        • select a,sum(b),count(distinct c),count(distinct d) from test group by a
      • 优化后
        • select a,sum(b) as b,count(c) as c,count(d) as d from(select a,0 as b,c,null as d from test group by a,c union all select a,0 as b,null as c,d from test group by a,d union all select a,b,null as c,null as d from test)tmp1 group by a;

     

     

    1、fetch task

    在使用Hive的时候,有时候只是想取表中某个分区的前几条的记录看下数据格式,比如一个很常用的查询:

     

    1

     

    select* fromfoo wherepartition_column=bar limit 10;

    这种对数据基本没什么要求,随便来点就行,既然如此为什么不直接读取本地存储的数据作为结果集呢。

    Hive命令都要转换为MapReduce任务去执行,但是因为启动MapReduce需要消耗资源,然后速度还很慢(相比较于直接从本地文件中读取而言),所以Hive对于查询做了优化,对于某些查询可以不启动MapReduce任务的就尽量不去启动MapReduce任务,而是直接从本地文件读取。

    在hive-site.xml中有三个fetch task相关的值:

    hive.fetch.task.conversion

    hive.fetch.task.conversion.threshold

    hive.fetch.task.aggr

     

    主要用到hive.fetch.task.conversion

    none:关闭fetch task优化

    minimal:只在select *、使用分区列过滤、带有limit的语句上进行优化

    more:在minimal的基础上更加强大了,select不仅仅可以是*,还可以单独选择几列,并且filter也不再局限于分区字段,同时支持虚拟列(别名)

    hive.fetch.task.conversion.threshold

    在输入大小为多少以内的时候fetch task生效,默认1073741824 byte = 1G。

    hive.fetch.task.aggr

    对于没有group by的聚合查询,比如select count(*) from src,这种最终都会在一个reduce中执行,像这种查询,可以把这个置为true将将其转换为fetch task,这可能会节约一些时间。

     

    2、strict mode:严格模式设置,严格模式下将会限制一些查询操作

    开启严格模式

    hive提供的严格模式,禁止3种情况下的查询模式。

    a:当表为分区表时,where字句后没有分区字段和限制时,不允许执行。

    b:当使用order by语句时,必须使用limit字段,因为order by 只会产生一个reduce任务。

    c:限制笛卡尔积的查询。sql语句不加where不会执行

     

    3、推测执行

    例如一个Job应用有10个MapReduce任务(map 及reduce),其中9个任务已经完成,那么application Master会在另外启动一个相同的任务来运行未完成的那个,最后哪个先运行完成就把另一个kill掉

     

    启用speculative最大的好处是,一个map执行的时候,系统会在其他空闲的服务器上启动相同的map来同时运行,哪个运行的快就使用哪个的结果,另一个运行慢的在有了结果之后就会被kill。

    hive.mapred.reduce.tasks.speculative.execution=true;

     

     

     

    SQL

    1、写一张表中有id和name 两个字段,查询出name重复的所有数据

    select*from xi a where (a.username) in (select username from xi groupby username havingcount(*) >1)

     

    2、查询出所有数据进行分组之后,和重复数据的重复次数的查询数据

    select id , count(1) as '重复次数' from table1

    group by id having count(1) > 1

    order by id

     

    1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断

    select * from table1 where peopleId in (

    select peopleId from table1 group by peopleId having count(1) > 1)

    2、删除表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断,只留有rowid最小的记录

    2.、

     delete ID1,email from email e1

     where rowid  >(select min(rowid) from email e2 where e1.email = e2.email AND e1.id1 = e2.id1);

     

    2.2、

    CREATE TABLE tmp_table AS

    with rank as(

    select t.peopleId , t.xh ,rank() over(partition by t.peopleId order by rowid) row_id

    from table1 t

    )

    SELECT * FROM rank

    where row_id = 1;

     

    DELETE FROM table1 ;

     

    INSERT INTO table1 SELECT * FROM tmp_table ;

     

    3、连续活跃天数

    select user_id , count(1)

    from

    (

    select user_id , date_id ,lead(date_id) over(partiton by user_id order by date_id) as next_date_id

    from

    (select user_id, date_id from table1

    group by user_id, date_id

    )

    )

    where datediff(date_id , next_date_id) = 1

    group by user_id

     

     

    题1:

    用户登陆日志

    app, user_id, datetime

    a1,user1,2020-01-01 00:00:00

    a2,user2,2020-01-01 00:00:01

    a3,user3,2020-01-01 00:00:02

    a4,user4,2020-01-01 00:00:03

    ……

    输出每个app下访问次数最多的5个用户

     

    select app , user_id from(

    select app , user_id, rank() over(partition app order by cnt desc) row_id

    from

    (

    select app , user_id , count(1) as cnt

    from table1

    group by app , user_id

    )

    )

    where row_id <=

     

     

     

     

     

     

     

    select store,count(distinct uid) as uv from Visit group by store;

     

    select * from Users order by age desc, total;

     

     

    考点:列转行

    select  stage_someone, count(distinct UID)  from  LifeStage  lateral  view  explode(split(stage,','))  LifeStage_tmp  as stage_someone  group  by  stage_someone;

     

     

    select UID,concat_ws(',',collect_set(stage)) as stages from LifeStage group by UID;

    考点:行转列

    explode与lateral view在关系型数据库中本身是不该出现的,因为他的出现本身就是在操作不满足第一范式的数据(每个属性都不可再分),

    本身已经违背了数据库的设计原理(不论是业务系统还是数据仓库系统),不过大数据技术普及后,很多类似pv,uv的数据,在业务系统中是存贮在非关系型数据库中,

    用json存储的概率比较大,直接导入hive为基础的数仓系统中,就需要经过ETL过程解析这类数据,explode与lateral view在这种场景下大显身手。

    explode作用是处理map结构的字段,使用案例如下(hive自带map,struct,array字段类型,但是需要先定义好泛型,所以在此案例不使用):

    建表语句:

    drop table explode_lateral_view;

    create table explode_lateral_view

    (`area` string,

    `goods_id` string,

    `sale_info` string)

    ROW FORMAT DELIMITED

    FIELDS TERMINATED BY '|'

    STORED AS textfile;

     

     

    导入数据:

    a:shandong,b:beijing,c:hebei|1,2,3,4,5,6,7,8,9|[{"source":"7fresh","monthSales":4900,"userCount":1900,"score":"9.9"},{"source":"jd","monthSales":2090,"userCount":78981,"score":"9.8"},{"source":"jdmart","monthSales":6987,"userCount":1600,"score":"9.0"}]

    表内数据如下

     

    explode的使用:

    我们只拆解array字段,语句为select explode(split(goods_id,',')) as goods_id from explode_lateral_view;

    结果如下

     

     

    拆解map字段,语句为select explode(split(area,',')) as area from explode_lateral_view;

     

    拆解json字段

     

    这个时候要配合一下get_json_object

     

     

    我们想获取所有的monthSales,第一步我们先把这个字段拆成list,并且拆成行展示:

    select explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{')) as  sale_info from explode_lateral_view;

     

    然后我们想用get_json_object来获取key为monthSales的数据:

    select get_json_object(explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{')),'$.monthSales') as  sale_info from explode_lateral_view;

    然后挂了FAILED: SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions

    UDTF explode不能写在别的函数内

    如果你这么写,想查两个字段,select explode(split(area,',')) as area,good_id from explode_lateral_view;

    会报错FAILED: SemanticException 1:40 Only a single expression in the SELECT clause is supported with UDTF's. Error encountered near token 'good_id'

    使用UDTF的时候,只支持一个字段,这时候就需要LATERAL VIEW出场了

     

    LATERAL VIEW的使用:

    侧视图的意义是配合explode(或者其他的UDTF),一个语句生成把单行数据拆解成多行后的数据结果集。

    select goods_id2,sale_info from explode_lateral_view LATERAL VIEW explode(split(goods_id,','))goods as goods_id2;

     

     

    其中LATERAL VIEW explode(split(goods_id,','))goods相当于一个虚拟表,与原表explode_lateral_view笛卡尔积关联。

    也可以多重使用

    select goods_id2,sale_info,area2

    from explode_lateral_view 

    LATERAL VIEW explode(split(goods_id,','))goods as goods_id2 

    LATERAL VIEW explode(split(area,','))area as area2;

    也是三个表笛卡尔积的结果

     

    现在我们解决一下上面的问题,从sale_info字段中找出所有的monthSales并且行展示

    select get_json_object(concat('{',sale_info_r,'}'),'$.monthSales') as monthSales from explode_lateral_view 

    LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{'))sale_info as sale_info_r;

     

    最终,我们可以通过下面的句子,把这个json格式的一行数据,完全转换成二维表的方式展现

    select get_json_object(concat('{',sale_info_1,'}'),'$.source') as source,

         get_json_object(concat('{',sale_info_1,'}'),'$.monthSales') as monthSales,

         get_json_object(concat('{',sale_info_1,'}'),'$.userCount') as monthSales,

         get_json_object(concat('{',sale_info_1,'}'),'$.score') as monthSales

      from explode_lateral_view 

     

    LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{'))sale_info as sale_info_1;

     

     

     

     

     

     

    展开全文
  • hive面试题总结(2020最新版)

    千次阅读 多人点赞 2020-03-27 15:05:23
    5.1、行转列函数5.2、列转行函数5.3、Rank排名函数5.4、窗口函数(开窗函数)六、UDF、UDAF、UDTF相关面试题6.1、UDF、UDAF、UDTF的区别?6.2、怎么自定义UDF、UDAF、UDTF函数?七、hive怎么解决数据倾斜?八、hive...
  • 1.Outline结构大纲功能显示当前文件的结构,是由哪些函数和变量组成的。...不同类型函数有不同颜色标识。 2.查看错误信息双击错误信息,到达代码所在行: 3.代码调试功能①设置断点 效果图: ②开始Debug(调
  • 以牺牲部分公平性及带宽利用率之代价,换取了着BT都能流畅传输的效果。 快速安装 您可以使用vcpkg库管理器下载并安装kcp: git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./...
  • 在.vimrc里面定义了使用cscope的快捷键,比如将光标放在某个函数上使用命令",sc"就可以查看这个函数哪些函数调用过, 【#】全屏显示 <F11> :genfiletags.sh 是让终端全屏显示 <F12>add cscope.out 在查找文件...
  • vim开发环境配置

    2019-10-03 13:47:33
    一、大饱眼福 ...文件索引功能,也就是可以知道这个文件里面有哪些函数,变量,宏定义,结构体,类等等 文件目录快速浏览,可以通过目录窗口来打开自己想要打开的文件,创建删除目录等功能 自动补全...
  • STM32串口通讯USART

    2020-11-30 15:41:44
    一、STM32的USART窗口通讯程序 (一)基于寄存器与基于固件库的stm32 LED流水灯例子的编程...大多数情况下,你不需要知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。 (二)STM32的USART窗口通讯程序 1、打开
  • Visual Studio 提供的命令行工具:Dumpbin——为了查看一个DLL中有哪些导出函数1:开始—>运行—>输入“cmd”(打开DOC窗口)2:使用Dumpbin.exe打开需要导出函数的DLL。如果在其他目录下无法执行Dumpbin命令(Visual ...
  • C# winform中 选择文件和保存文件

    万次阅读 多人点赞 2017-03-14 18:23:02
    我们在使用桌面软件的时候...话不多说,先写两段代码让你体验一下效果,具体的对象有哪些功能,可以单独查一查相应的函数。**选择文件功能** 你可以创建一个button按钮,把代码直接放到按钮的点击事件中,当点击按
  • 关于Servlet的新发现

    2011-09-29 15:45:08
    最近要在系统中做一个任务监控,即是,每次登录进去之后就能看到服务器上有哪些任务在运行,也可以看到自己提交的任务的进度。这样的话,每次提交完任务不用一直着浏览器窗口了,随时都可以登录系统查看任务进度。...
  • javascript常用对象梳理

    2012-06-23 21:29:38
    求该没有标准工具栏、地址栏、链接工具栏、菜单栏,但状态栏,窗口中打 的网页地址为: http://www.dlrtvu.edu.cn 。 2. close方法 语法格式: window.close() 功能:close方法用于自动关闭浏览器窗口。 ...
  • 哪些函数建议使用__inline 92 大数据量处理CPU时间限制 92  为什么不能使用FOR、WHILE连续处理大数据量 93  CPU时间限制 93  提示 93  使用ISHELL_POSTEVENT消息处理。 93  消息机制 93  处理消息...
  • 哪些函数建议使用__inline 92 大数据量处理CPU时间限制 92  为什么不能使用FOR、WHILE连续处理大数据量 93  CPU时间限制 93  提示 93  使用ISHELL_POSTEVENT消息处理。 93  消息机制 93  处理消息...
  • BitBlt和StretchBlt函数有什么区别 什么是掩码位图以及如何创建 如何利用掩码位图制作透明图片 如何绘制半透明位图 如何缩放图片 如何对图形进行局部放大 如何将转换DIB位图为DDB位图 如何将转换DDB位图为DIB位图 ...
  • VC++常用功能实例

    2010-01-25 23:28:46
    哪些函数是文档、视图相互处理用的◆ 23 ◆如何建立一个基于对话框一程序◆ 23 ◆如何建立一个线程◆ 24 ◆如何让窗口产生一个图标(从应用程序资源中取出)◆ 24 ◆如何得到一个edit的录入的值◆ 24 ◆如何启动...
  • 中文API支持库(1.0-0

    2009-04-17 08:28:19
    注解:如磁盘卷已被压缩,可检查这个函数的结果是否与GetFileSize函数的结果异,从而判断文件是否也被压缩(如异,表明文件已被压缩)。 _取当前目录() 返回值为写到lpBuffer的字节数。如nBufferLength的长度...
  • Visual Studio程序员箴言--详细书签版

    热门讨论 2012-10-16 20:37:39
    本:16 页码:205 版次:1-1 所属分类:计算机 > 软件与程序设计 > .NET > Visual Studio.NET 内容简介  visual studio是微软公司推出的、目前最流行的windows平台应用程序开发环境。本书介绍了各种visual ...
  • Visual Studio程序员箴言中文扫描PDF

    热门讨论 2010-12-28 01:04:18
    技巧5.50 为何“对象浏览器”很多可以绑定的命令(以及如何创建一个可清除搜索结果的键盘快捷键) 135 技巧5.51 在“对象浏览器”中使用全局命令视图.前进(alt+右箭头)和视图.后退(alt+左箭头) 136 第6章 了解...
  • 标记菜单的实现原理、图形菜单的实现及常犯错误的分析,GetSystemMetrics的应用,快捷弹出菜单的实现方式及其命令响应函数有效范围(与弹出菜单时所指定的父窗口密切的关系,最底层的子窗口具有最优先的处理机会)...
  • 比如在Emacs里面,俺C-x b之后它就让我输入一个buffer 名,虽然它都知道有哪些buffer, 但还是让我输,少输入几个字母敲了回车,结果它给我新创建了一个buffer ! 真是相当不给力啊。ido/anything 这样的扩展就是把备...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    1.30如何判断哪些标识符可以使用,哪些被保留了? 初始化 1.31 对于没有显式初始化的变量的初始值可以作怎样的假定?如果一个全局变量初始值为“零”,它可否作为空指针或浮点零? 1.32 下面的代码为什么不能...

空空如也

空空如也

1 2 3 4 5
收藏数 91
精华内容 36
关键字:

开窗函数有哪些