DuckDB:聚合 JSON 列表(唯一)

问题描述 投票:0回答:1

有没有办法将嵌套值列表从 json 列展平为不同值列表:

即:

from: {"unique_values":[["105125"],["105125"],["105125","0]]}
to: {"unique_values": ["105125","0"]
sql duckdb
1个回答
0
投票

初步尝试使用:

tbl = duckdb.sql("""
from (values
   ('{"id":1,"values":[["1"],["1"],["1","0"]]}'),
   ('{"id":2,"values":[["2"],["3"],["1","3"]]}')
)
select col0::json as j
""")
duckdb.sql("""
from tbl
select json_merge_patch(j, 
   {
      "values": 
         json_transform(j.values, '"VARCHAR[][]"')
           .flatten()
           .list_distinct()
    }::json
) as j
"""
)
┌─────────────────────────────────┐
│                j                │
│              json               │
├─────────────────────────────────┤
│ {"values":["0","1"],"id":1}     │
│ {"values":["1","3","2"],"id":2} │
└─────────────────────────────────┘

但是,一些潜在的问题:

  • list_distinct()
    无法保留原来的值顺序。
  • json_merge_patch()
    失去原来的按键顺序。

保留原有订单

如果处理其他键和顺序很重要,似乎需要取消嵌套完整的 json 对象。

我在这里使用 json_group_struct() 来“动态”提取“模式”。

schema = duckdb.sql("""
from tbl select json_group_structure(j)
""").fetchone()[0]
'{"id":"UBIGINT","values":[["VARCHAR"]]}'

这有点啰嗦,因为我们手动取消嵌套、展平、区分,并使用 2 个单独的

row_number()
表达式来表示行和值顺序。

duckdb.sql(f"""
with 
data as (
   from tbl 
   select 
      row_number() over () row_number,
      unnest(json_transform(j, '{schema}')) 
),
distinct_data as (
   from (
      from data
      select * replace unnest(values.flatten()) as values
   )
   select distinct on (row_number, values) 
      *, 
      row_number() over () as list_idx
),
distinct_lists as (
   from distinct_data
   select 
      first(columns(* exclude (values, list_idx))),
      list(values order by list_idx) as values
   group by id
   order by row_number
),
result as (
   from distinct_lists select * exclude row_number
)
from result 
select result::json as j
""")
┌─────────────────────────────────┐
│                j                │
│              json               │
├─────────────────────────────────┤
│ {"id":1,"values":["1","0"]}     │
│ {"id":2,"values":["2","3","1"]} │
└─────────────────────────────────┘

我希望有一种方法可以简化这个过程。

© www.soinside.com 2019 - 2024. All rights reserved.