【问题标题】:A SQL query to filter through a stringified json array用于过滤字符串化 json 数组的 SQL 查询
【发布时间】:2021-04-13 16:26:57
【问题描述】:

我正在努力编写一个可以以某种方式从表中检索结果的 sql 查询。

我有一个可能包含以下类型数据的表。在该表中,前项列中的值是字符串形式的 sku 排序列表

Id | antecendents | ...         | ....
1  | ["a","b","c"]| ...         | .....
2  | ["a"]        | ...         | .....
3  | ["a","b"]    | ...         | .....
4  | ["a","c"]    | ...         | .....
5  | ["a","c","x"]| ...         | .....
6  | ["a","y","c"]| ...         | .....
7  | ["c"]        | ...         | .....

现在假设我有一组 skus(例如“a”和“c”)

我只想从表中检索那些包含“a”和“c”的所有组合的行,但没有别的。所以我的查询将返回以下内容

Id | antecendents | ...         | ....
2  | ["a"]        | ...         | .....
4  | ["a","c"]    | ...         | .....
7  | ["c"]        | ...         | .....

我可以编写一个查询来获取部分结果并在代码中进一步过滤它,但将这一切都在一个 sql 查询中完成会更有效。

任何帮助将不胜感激。

【问题讨论】:

    标签: mysql sql mysql-json


    【解决方案1】:

    我想出了这个解决方案。去掉“a”元素,然后用生成的数组,去掉“c”元素,然后将其与空的json_array() 进行比较。如果先行词减去“a”元素减去“c”元素是一个空数组,则没有其他元素,这就是您想要的行之一。

    select id, antecedents from (
      select id, antecedents, coalesce(json_remove(antecedents, json_unquote(json_search(antecedents, 'one', 'a'))), antecedents) as a from mytable ) as t
    where coalesce(json_remove(a, json_unquote(json_search(a, 'one', 'c'))), a) = json_array()
    

    结果:

    +----+-------------+
    | id | antecedents |
    +----+-------------+
    |  2 | ["a"]       |
    |  4 | ["a", "c"]  |
    |  7 | ["c"]       |
    +----+-------------+
    

    但老实说,编写如此复杂的代码并不实际。难写、难读、难调试、难维护或修改。

    永远记住这个智慧:

    “首先,调试的难度是编写代码的两倍。因此,如果你尽可能巧妙地编写代码,那么根据定义,你就不够聪明,无法调试它。” — 布赖恩·克尼汉

    如果不使用 JSON 数组会容易得多。每行只存储一个元素。

    create table mytable2 (id int, antecedent varchar(10), primary key (id, antecedent));
    
    insert into mytable2 values
    (1, 'a'), (1,'b'), (1,'c'),
    (2, 'a'),
    (3, 'a'), (3, 'b'),
    (4, 'a'), (4, 'c'),
    (5, 'a'), (5, 'c'), (5, 'x'),
    (6, 'a'), (6, 'y'), (6, 'c'),
    (7, 'c');
    

    现在构思查询要容易得多。您甚至可以将值集作为 JSON 数组返回。

    select m1.id, json_arrayagg(m1.antecedent) as antecedents
    from mytable2 m1 left outer join mytable2 as m2
      on m1.id = m2.id and m2.antecedent not in ('a','c')
    where m2.id is null
    group by m1.id
    

    结果:

    +----+-------------+
    | id | antecedents |
    +----+-------------+
    |  2 | ["a"]       |
    |  4 | ["a", "c"]  |
    |  7 | ["c"]       |
    +----+-------------+
    

    如果您想将元素视为集合中的离散元素,关系数据库已经有支持它的方法。不要使用 JSON。

    【讨论】:

    • 这是完美的。我根据您的建议更改了存储前因的方式并得到了我需要的结果。
    猜你喜欢
    • 2022-10-13
    • 2011-06-04
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    相关资源
    最近更新 更多