当前行包含多个值时,BigQuery SQL JSON返回其他行

发布于 2025-01-27 21:39:16 字数 512 浏览 4 评论 0原文

我有一个表,看起来像

keyA           | data:{"value":false}}
keyB           | data:{"value":3}}
keyC           | data:{"value":{"paid":10,"unpaid":20}}} 

keyakeyb我可以轻松地使用JSON_EXTRACT_SCALAR轻松提取单个值,但是对于keyc < /code>我想返回多个值并更改密钥名称,因此最终输出看起来像这样:

keyA           | false
keyB           | 3
keyC-paid      | 10
keyD-unpaid    | 20

我知道我可以使用Unnest和JSON__EXTRACT多个值,并创建其他但不确定如何组合它们以将关键列名称调整为出色地?

I have a table that looks like this

keyA           | data:{"value":false}}
keyB           | data:{"value":3}}
keyC           | data:{"value":{"paid":10,"unpaid":20}}} 

For keyA,keyB I can easily extract a single value with JSON_EXTRACT_SCALAR, but for keyC I would like to return multiple values and change the key name, so the final output looks like this:

keyA           | false
keyB           | 3
keyC-paid      | 10
keyD-unpaid    | 20

I know I can use UNNEST and JSON_EXTRACT multiple values and create additional but unsure how to combine them to adjust the key column name as well?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱娆 2025-02-03 21:39:16

甚至更通用的方法

create temp function  extract_keys(input string) returns array<string> language js as """
  return Object.keys(JSON.parse(input));
  """;
create temp function  extract_values(input string) returns array<string> language js as """
  return Object.values(JSON.parse(input));
  """;
create temp function extract_all_leaves(input string) returns string language js as '''
  function flattenObj(obj, parent = '', res = {}){
    for(let key in obj){
        let propName = parent ? parent + '.' + key : key;
        if(typeof obj[key] == 'object'){
            flattenObj(obj[key], propName, res);
        } else {
            res[propName] = obj[key];
        }
    }
    return JSON.stringify(res);
  }
  return flattenObj(JSON.parse(input));
  ''';
select col || replace(replace(key, 'value', ''), '.', '-') as col, value, 
from your_table,
unnest([struct(extract_all_leaves(data) as json)]),
unnest(extract_keys(json)) key with offset
join unnest(extract_values(json)) value with offset
using(offset)    

如果应用于您的问题中的样本数据,

- 输出为 ”在此处输入图像描述”

这种方法的好处是它非常通用,因此可以处理JSON中的任何层次的嵌套,

例如以下数据/表

输出为

”在此处输入图像描述

Even more generic approach

create temp function  extract_keys(input string) returns array<string> language js as """
  return Object.keys(JSON.parse(input));
  """;
create temp function  extract_values(input string) returns array<string> language js as """
  return Object.values(JSON.parse(input));
  """;
create temp function extract_all_leaves(input string) returns string language js as '''
  function flattenObj(obj, parent = '', res = {}){
    for(let key in obj){
        let propName = parent ? parent + '.' + key : key;
        if(typeof obj[key] == 'object'){
            flattenObj(obj[key], propName, res);
        } else {
            res[propName] = obj[key];
        }
    }
    return JSON.stringify(res);
  }
  return flattenObj(JSON.parse(input));
  ''';
select col || replace(replace(key, 'value', ''), '.', '-') as col, value, 
from your_table,
unnest([struct(extract_all_leaves(data) as json)]),
unnest(extract_keys(json)) key with offset
join unnest(extract_values(json)) value with offset
using(offset)    

if applied to sample data in your question - output is

enter image description here

Benefit of this approach is that it is quite generic and thus can handle any level of nesting in json

For example for below data/table

enter image description here

the output is

enter image description here

人间☆小暴躁 2025-02-03 21:39:16

尝试一下:

WITH sample AS (
  SELECT 'keyA' AS col, '{"value":false}' AS data
   UNION ALL
  SELECT 'keyB' AS col, '{"value":3}' AS data
   UNION ALL
  SELECT 'keyC' AS col, '{"value":{"paid":10,"unpaid":20}}' AS data
)
SELECT col || IFNULL('-' || k, '') AS col,
       IFNULL(v, JSON_VALUE(data, '$.value')) AS data
  FROM (
    SELECT col, data, 
           `bqutil.fn.json_extract_keys`(JSON_QUERY(data, '$.value')) AS keys,
           `bqutil.fn.json_extract_values`(JSON_QUERY(data, '$.value')) AS vals
      FROM sample
  ) LEFT JOIN UNNEST(keys) k WITH OFFSET ki 
    LEFT JOIN UNNEST(vals) v WITH OFFSET vi ON ki = vi;

“在此处输入图像描述”

Try this one:

WITH sample AS (
  SELECT 'keyA' AS col, '{"value":false}' AS data
   UNION ALL
  SELECT 'keyB' AS col, '{"value":3}' AS data
   UNION ALL
  SELECT 'keyC' AS col, '{"value":{"paid":10,"unpaid":20}}' AS data
)
SELECT col || IFNULL('-' || k, '') AS col,
       IFNULL(v, JSON_VALUE(data, '$.value')) AS data
  FROM (
    SELECT col, data, 
           `bqutil.fn.json_extract_keys`(JSON_QUERY(data, '$.value')) AS keys,
           `bqutil.fn.json_extract_values`(JSON_QUERY(data, '$.value')) AS vals
      FROM sample
  ) LEFT JOIN UNNEST(keys) k WITH OFFSET ki 
    LEFT JOIN UNNEST(vals) v WITH OFFSET vi ON ki = vi;

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文