【问题标题】:SQL parse string separated by | into keys and valuesSQL 解析字符串由 | 分隔进入键和值
【发布时间】:2019-12-19 18:56:50
【问题描述】:

我在解析用管道分隔的字符串方面需要帮助。第一个数字是键,管道之后的后续字符串是该键的数百个值

|01|00109394|05|84|08|34353637

这应该被分解成 第一个管道之后的长度= 2 数字的键 值:在每个键之后

  • first_key = 01,值 = 00、10、93、94
  • second_key = 05,值 = 84
  • 等等……

脚本应该打破字符串并分解为行,以便“key”列将包含所有键,“values”列将包含所有所有值

样本输出

KEY Value
01  00
01  10
01  93
01  94
05  84
08  34
08  35

这是我写的但不工作的代码

Select my_key, explode(str_to_map(my_key,'[|]','[|]')) as (Key, Value)
from test_table;

请建议如何解析这个字符串

【问题讨论】:

  • 这是什么 DBMS 以及“不工作”的详细含义是什么?
  • 还可以考虑修复该架构并从一开始就以标准化方式存储数据。应该有一个表,其中一列用于键,另一列用于值,如果顺序很重要,可能还有一个用于序数。每个值在该表中应该有一行。
  • 查询将从 hive 获取数据。我无法修复架构,因为它是作为日志收集的数据,必须保持这种状态。它不起作用,因为它通过管道将整个字符串转换为“值”来拆分字符串。我需要它以一种读取“键”的方式进行拆分,然后将后续值作为键的“值”读取。然后它应该读取第二个键并放入下一行。
  • 当键和值都由相同的管道分隔符“|”分隔时,我不知道如何从字符串中获取键
  • 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称。 Why should I tag my DBMS

标签: sql parsing hive split hiveql


【解决方案1】:

我使用 split 和 explode 完成了两次。第一次获取未拆分的键和值,第二次将值分隔两个字符。阅读代码中的cmets:

with your_data as (
select stack (1, '|01|00109394|05|84|08|34353637') as str
)

select --s.initial_str, 
       s.key, v.val
from
(
select s.pos, s.initial_str, s.key, s.val
from
(
select s.initial_str,
       s.pos, --0 and even positions are keys, odd are values
       s.val as key, 
       --assign the value to each key, which is the next eploded value 
       lead(val,1) over(partition by s.initial_str order by s.pos) as val --some keys from main table are in partition by clause
from       
( --explode string
select d.str initial_str, s.pos, s.val
  from your_data d lateral view outer posexplode(split(regexp_replace(str,'(^\\|)|(\\|$)',''),'\\|')) s as pos, val --remove leading and trailing pipe and explode
) s
)s
where s.pos%2=0 --filter keys with assigned values only (0 and even are rows we need)
) s 
--explode each two chars
--(?<=\\G.{2}) matches an empty string that has the last match (\\G) followed by two characters (.{2}) before it (?<=)
lateral view outer explode(split(s.val,'(?<=\\G.{2})')) v as val 
where v.val!=''
;

结果:

01      00
01      10
01      93
01      94
05      84
08      34
08      35
08      36
08      37

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2018-07-31
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多