【问题标题】:How to cast a string to array of struct in HiveQL如何在 HiveQL 中将字符串转换为结构数组
【发布时间】:2017-06-09 14:47:19
【问题描述】:

我有一个带有“周期”列的配置单元表,列的类型是字符串。

该列的值如下:

[{periode:20160118-20160205,nb:1},{periode:20161130-20161130,nb:1},{periode:20161130-20161221,nb:1}]
[{periode:20161212-20161217,nb:0}]

我想将此专栏投到array<struct<periode:string, nb:int>>。 最终目标是按周期制作一个原始文件。 为此,我想在列周期上使用带有爆炸的横向视图。 这就是为什么我想将其转换为array<struct<string, int>>

感谢您的帮助。 西迪

【问题讨论】:

  • 不清楚你想要的最终结果是什么。

标签: arrays struct hive explode hiveql


【解决方案1】:

我意识到这个问题是 1YO,但我遇到了同样的问题并使用 json_split brickhouse UDF 解决了它。

SELECT EXPLODE(
    json_split(
        '[{"periode":"20160118-20160205","nb":1},{"periode":"20161130-20161130","nb":1},{"periode":"20161130-20161221","nb":1}]'
));

col
{"periode":"20160118-20160205","nb":1}
{"periode":"20161130-20161130","nb":1}
{"periode":"20161130-20161221","nb":1}

对不起,意大利面条代码。

还有一个类似的问题here 使用 JSON 数组而不是 JSON 字符串。情况不一样,但对于任何面临此类任务的人来说,它可能在更大的背景下有用。

【讨论】:

    【解决方案2】:

    你不需要“投射”任何东西,你只需要分解数组然后解压结构。我为您的数据添加了一个索引,以便更清楚地了解事情的结局。

    数据

    idx arr_of_structs
    0   [{periode:20160118-20160205,nb:1},{periode:20161130-20161130,nb:1},{periode:20161130-20161221,nb:1}]
    1   [{periode:20161212-20161217,nb:0}]
    

    查询

    SELECT idx                          -- index
      , my_struct.periode AS periode    -- unpacks periode
      , my_struct.nb      AS nb         -- unpacks nb
    FROM database.table
    LATERAL VIEW EXPLODE(arr_of_structs) exptbl AS my_struct
    

    输出

    idx     periode                 nb
    0       20160118-20160205       1
    0       20161130-20161130       1
    0       20161130-20161221       1
    1       20161212-20161217       0
    

    您的问题有点不清楚所需的结果是什么,但是一旦您更新它,我就会相应地修改查询。


    编辑

    上述解决方案不正确,我没有发现您的输入是STRING

    查询

    SELECT REGEXP_EXTRACT(tmp_arr[0], "([0-9]{8}-[0-9]{8})") AS periode
      , REGEXP_EXTRACT(tmp_arr[1], ":([0-9]*)")              AS nb
    FROM (
      SELECT idx
        , pos
        , COLLECT_SET(tmp_col) AS tmp_arr
      FROM (
        SELECT idx
          , tmp_col
          , CASE WHEN PMOD(pos, 2) = 0 THEN pos+1 ELSE pos END AS pos
        FROM (
          SELECT *
            , ROW_NUMBER() OVER () AS idx
          FROM database.table ) x
        LATERAL VIEW POSEXPLODE(SPLIT(periode, ',')) exptbl AS pos, tmp_col ) y
      GROUP BY idx, pos) z
    

    输出

    periode                 nb
    20160118-20160205       1
    20161130-20161130       1
    20161130-20161221       1
    20161212-20161217       0    
    

    【讨论】:

    • 我的 Json 很大 - 大约压缩 600+ MB REGEXP_EXTRACT 内存不足!
    • @SumitKumarGhosh 是 600 MB 大吗?
    • 是的,我们也有同样的想法,但是当作业运行时,它会出现堆错误。而且我们无法处理这些文件。 600 MB 是压缩一个 json 的最大大小 - 这需要拆分 - 所以这似乎是作为一个字符串加载的。因此失败了!
    【解决方案3】:

    如何使用拆分功能?你应该能够做类似的事情

    select nb, period from 
    (select split(periode, "-") as periods, nb from yourtable) t
    LATERAL VIEW explode(periods) sss AS period;
    

    我没试过,但它应该可以工作:)

    编辑:如果您在模式 date-date-date.. 和列 nb 之后有列句点,则上述内容应该有效,但看起来情况并非如此。以下查询应该适合您(详细但有效)

    select period, nb from (
    select 
    regexp_replace(split(split(tok1,",")[1],":")[1], "[\\]|}]", "") as nb,
    split(split(split(tok1,",")[0],":")[1],"-") as periods
    from
    (select split(YOURSTRINGCOLUMN, "},") as s1 from YOURTABLE) 
    r1 LATERAL VIEW explode(s1) ss1 AS tok1
    ) r2 LATERAL VIEW explode(periods) ss2 AS period;
    

    【讨论】:

    • SPLIT(periode, "-") 没有意义; periode 是结构数组中的列名。
    • 我有一个带有“周期”列的配置单元表,列的类型是字符串.....他有两列..
    • 不,这行不通。 OP 特别声明他们的数据类型为array<struct<periode:string, nb:int>>。您不能在数组上调用 regex_replace()split()
    • 他没有数组......他的数据是每个字符串,你假设它在一个数组中,因为数据看起来像一个数组。他说我们希望将字符串转换为结构...如果需要,请等待更多说明:)
    • 没问题,如果我们谈论大量数据,您的解决方案更干净但效率低得多,没有窗口函数的解决方案不会减少相位,如果他正在使用大量数据
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2015-11-11
    • 2020-12-04
    相关资源
    最近更新 更多