我得到了一个有1列的表,它是字符串类型,但里面看起来像是json类型.

该值如下所示

包含值的'old_id'

[{"name":"Entitas Penugasan","id":"6415","value":"HIJRA"},
 {"name":"Function","id":"10594","value":"People & Culture"},
 {"name":"Unit","id":"10595","value":"Organization Development"},
 {"name":"Tribe","id":"10602","value":"Shared Service"}
]

'new_id'列带值

[{"name":"Entitas Penugasan","id":"6415","value":"AFS"},
 {"name":"Function","id":"10594","value":"Finance"},
 {"name":"Unit","id":"10595","value":"Finance Operations"},
 {"name":"Tribe","id":"10602","value":"Commercial"}
]

我需要SQL Athena Query从那些json列中创建列old_name、old_id、old_value、new_name、new_id、new_value

我试过用

REGEXP_EXTRACT(old_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 1) AS old_name,
REGEXP_EXTRACT(new_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 1) AS new_name,
REGEXP_EXTRACT(old_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 2) AS old_id,
REGEXP_EXTRACT(new_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 2) AS new_id,
REGEXP_EXTRACT(old_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 3) AS old_value,
REGEXP_EXTRACT(new_id, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 3) AS new_value

但它只生成1行,即使在列中,它也显示4个"数组"

The query should generate 4 rows, looks like below enter image description here

id old_name new_name old_id new_id old_value new_value
A Entitas Penugasan Entitas Penugasan 6415 6415 HIJRA AFS
A Function Function 10594 10594 People & Culture Finance
A Unit Unit 10595 10595 Organization Development Finance Operations
A Tribe Tribe 10602 10602 Shared Service Commercial

有没有办法在SQL Athena中做到这一点?


编辑:我在下面的查询中取得了一些进展

with raw_data as(
select id, user_id, old_custom_fields, new_custom_fields
    from my_table
    where 
    -- new_custom_fields <> '' and new_custom_fields<> 'None' and new_custom_fields is not null and
    id in (A)
),
splitted_data as (
    SELECT id, user_id,
    split(old_custom_fields, '},{') AS old_custom_field_id,
    split(new_custom_fields, '},{') AS new_custom_field_id
  FROM my_table
),
old_custom_field_id_unnest as (
SELECT
  *
 from splitted_data
CROSS JOIN UNNEST(old_custom_field_id) AS t (_old_custom_fields)
),
new_custom_field_id_unnest as (
SELECT
  *
 from splitted_data
CROSS JOIN UNNEST(new_custom_field_id) AS t (_new_custom_fields)
),
old_custom_field_cleaned as (
    select id, old_custom_field_id,
    REGEXP_EXTRACT(_old_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 1) AS old_name,
    REGEXP_EXTRACT(_old_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 2) AS old_id,
    REGEXP_EXTRACT(_old_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 3) AS old_value
    from old_custom_field_id_unnest
),
new_custom_field_cleaned as (
    select id, new_custom_field_id,
    REGEXP_EXTRACT(_new_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 1) AS new_name,
    REGEXP_EXTRACT(_new_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 2) AS new_id,
    REGEXP_EXTRACT(_new_custom_fields, '"name":"(.*?)","id":"(.*?)","value":"(.*?)"', 3) AS new_value
    from new_custom_field_id_unnest
)
select oc.id, old_name, new_name,
    old_id,new_id,
    old_value,new_value
    from old_custom_field_cleaned oc 
    join new_custom_field_cleaned nc on oc.id = nc.id

But this leads to duplicated rows, now I have 16 rows due to the join, still needs help in removing the unneeded rows enter image description here

推荐答案

您的数据不仅看起来像JSON,样例数据也是JSON,所以请将其作为一个整体进行处理.根据所使用的Presto/Trino版本的不同,实际处理可能会有所不同,但公共部分始终是解析JSON并将其强制转换为某个类型的array,然后取消嵌套.例如,您可以使用ROW(name varchar, id varchar, value varchar)(根据具体情况,备选方案可以只有JSONMAP(varchar, varchar)MAP(varchar, JSON)):

-- sample data
WITH dataset(old_id, new_id) AS (
    VALUES
        ('[{"id":"6415","value":"HIJRA", "name":"Entitas Penugasan"},
             {"name":"Function","id":"10594","value":"People & Culture"},
             {"name":"Unit","id":"10595","value":"Organization Development"},
             {"name":"Tribe","id":"10602","value":"Shared Service"}
          ]',
          '[{"name":"Entitas Penugasan","id":"6415","value":"AFS"},
             {"name":"Function","id":"10594","value":"Finance"},
             {"name":"Unit","id":"10595","value":"Finance Operations"},
             {"name":"Tribe","id":"10602","value":"Commercial"}
            ]'
         )
)

-- query
SELECT t.*
FROM dataset,
unnest(cast(json_parse(old_id) as array(row(name varchar, id varchar, value varchar))),
    cast(json_parse(old_id) as array(row(name varchar, id varchar, value varchar)))) as t(old_name, old_id, old_value, new_name, new_id, new_value); -- maybe as t(old, new) depending on engine and select t.old.name as old_name, ...

输出:

old_name old_id old_value new_name new_id new_value
Entitas Penugasan 6415 HIJRA Entitas Penugasan 6415 HIJRA
Function 10594 People & Culture Function 10594 People & Culture
Unit 10595 Organization Development Unit 10595 Organization Development
Tribe 10602 Shared Service Tribe 10602 Shared Service

上面的代码来自于假设数组以正确的顺序拥有"相同"的数据.就我个人而言,我会考虑根据ID:

-- sample data
WITH dataset(old_id, new_id) AS (
   -- ..
),

-- query 
old_values as (
    SELECT t.*
    FROM dataset,
    unnest(cast(json_parse(old_id) as array(row(name varchar, id varchar, value varchar)))) as t(name, id, value)
),
new_values as (
    SELECT t.*
    FROM dataset,
    unnest(cast(json_parse(new_id) as array(row(name varchar, id varchar, value varchar)))) as t(name, id, value)
)

SELECT o.id,
       o.name old_name,
       o.value old_value,
       n.name new_name,
       n.value new_value
FROM old_values as o
full outer join new_values as n on o.id = n.id;

输出:

id old_name old_value new_name new_value
6415 Entitas Penugasan HIJRA Entitas Penugasan AFS
10594 Function People & Culture Function Finance
10595 Unit Organization Development Unit Finance Operations
10602 Tribe Shared Service Tribe Commercial

Sql相关问答推荐

PostgreSQL:获取每家店铺收入最高的员工

Stack Exchange站点上的最短帖子(按正文长度计算,用户名为原始发帖(SEDE))

LEFT JOIN不显示计数0我期望的方式

从自定义日期和时间开始,每月具有给定状态的公司数量

检索上一个星期四和上一个星期三

收到%1、%2或%2邮箱的唯一客户

找到最新的连线

从数据库中查找总和大于或等于查询中的数字的数字

了解多个分组集

如何将不同层次的产品组和规格组合到最深一层?

向表中添加新列取决于表的日期列(unpivot)

如何创建snowflake表(动态查找数据类型)并从阶段加载(AWS S3)?

从选定记录中提取摘要作为值的划分

SQL Server 查询 WHERE LIKE

达到特定值时,从0开始累加求和

如何将特定值从 JSON 列中的一个字段移动到 PostgreSQL 中的另一个字段?

Select 多年的日期范围

如何对 SQL 表中的连续时间戳进行分组?

Select 随机行,使得列子组的组合是唯一的

在 SQL 中将行显示为列