【问题标题】:Snowflake- how to search for a value in json values without using hardcoded keys雪花 - 如何在不使用硬编码键的情况下搜索 json 值中的值
【发布时间】:2021-01-10 12:48:35
【问题描述】:

我有 json 列,其中包含从 d1 到 d32 的键,并且这些键具有某些值。 我现在想查询任何键中都不存在值的行。

Like - 任何不等于 abc 的维度。 所以我正在检查 d1!=abc 或 d2!=abc..... d32!=abc。 有更好的方法吗?

每一行都是一个 json 字段,具有 d1-d32 维度及其对应值的任意组合

【问题讨论】:

  • 我不确定我是否正确理解了您的问题,数据结构的示例会有所帮助。
  • 表格有一个 json 类型的列维度。 json 如下所示 - {d1: abc, d2:aaa, d3:bb} 和许多这样的 json 行。我想要做的是搜索 json 值为 abc 的行,但我不想在检查 json 键时对它们进行硬编码 - 维度.d1 = abc 或维度.d1 = abc。有没有办法在没有硬编码 d1 d2 d3 等的情况下进行搜索
  • 您可以编写 JavaScript UDF 来搜索值并返回 JSON 变体。传入要搜索的变体 JSON 和要查找的值。从那里它只是循环并构建输出 JSON。

标签: json snowflake-cloud-data-platform hardcode


【解决方案1】:

在我看来,您可以尝试编写存储过程或 JavaScript UDF。您的存储过程必须遍历所有行,并且对于每一行,它必须检查是否存在相应的维度 (1-32)。如果维度存在,它还必须检查值。

存储过程:https://docs.snowflake.com/en/sql-reference/stored-procedures-usage.html

UDF:https://docs.snowflake.com/en/sql-reference/udf-js.html

【讨论】:

    【解决方案2】:

    使用flatten(),您可以获取 json 中每个键的名称和值:

    with variants as (
    select 1 id, parse_json('{"d1":1, "d2":2, "d3":3}') data
    union all select 2, parse_json('{"d1":4, "d2":5, "d3":7}') 
    union all select 3, parse_json('{"d1":2, "d2":0, "d3":0}') 
    )
    
    select * 
    from variants, table(flatten(data));
    ;
    

    根据这些信息,您可以查看所有名为 d% 的键,并查找其中不存在的值 - 比如说 2:

    with variants as (
    select 1 id, parse_json('{"d1":1, "d2":2, "d3":3}') data
    union all select 2, parse_json('{"d1":4, "d2":5, "d3":7}') 
    union all select 3, parse_json('{"d1":2, "d2":0, "d3":0}') 
    )
    
    select id, not boolor_agg((iff(key like 'd%', value=2, true))) doesnt_have_a_2
    from variants, table(flatten(data))
    group by id
    ;
    

    这表明带有id=2 的行是唯一没有键具有值2 的行。

    作为替代方案,您还可以过滤 where 子句中的键名,而不是 iff

    with variants as (
    select 1 id, parse_json('{"d1":1, "d2":2, "d3":3}') data
    union all select 2, parse_json('{"d1":4, "d2":5, "d3":7}') 
    union all select 3, parse_json('{"d1":2, "d2":0, "d3":0}') 
    )
    
    select id, boolor_agg(value=2) 
    from variants, table(flatten(data))
    where key like 'd%'
    group by id
    ;
    

    【讨论】:

    • 谢谢,但我认为你的问题错了。我试图构建一个“任何”过滤器 - 这主要意味着搜索具有具有特定值的任何维度的记录。假设维度在 json 列中,d1 - d32 作为不同的维度(json 键)。每条记录可以有任意数量的维度键及其值。我现在在做什么 - array_construct(d1,d2,d3,d4...).toString -> 不包含 (SNAKE)。我如何不对 d1 - d32 键进行硬编码
    • 这不正是我所做的吗?请注意,我有维度 d1、d2 等......并且它们在 SELECT 查询中没有硬编码。尽管如此,我还是设法找到了所有没有键值为“2”的记录。
    • 对不起..我的错误。我正在尝试在没有硬编码维度的情况下实现“任何”子句。例如- d1:Snake,d2:平台下一行 d1:俄罗斯方块,d2:平台我想返回两行,因为它们的任何一个维度都不等于蛇。即使我将 json 展平,如何检查是否有任何一个维度与值不匹配?
    • 问题是我最多可以有 48 个维度,我不想去检查 d1!= snake 或 d2!=snake...... d48!=snake 作为一行可以有任何尺寸组合。
    • 我没有硬编码任何东西。如果有 d48,那也将包含在 boolor_agg(value=2) 之下。对于每个维度,它看起来是否等于 2,然后对所有维度执行“或”。如果 d1,d2,d3,..,d48 中的任何一个等于 2,则 boolor_agg() 的结果将为真,否则为假。请尝试使用您的数据。
    猜你喜欢
    • 2022-08-18
    • 1970-01-01
    • 2020-03-06
    • 2023-01-12
    • 2020-07-30
    • 2019-05-07
    • 2018-05-11
    • 1970-01-01
    • 2019-12-25
    相关资源
    最近更新 更多