【问题标题】:MySQL - Order elements by JSON value in array?MySQL - 按数组中的 JSON 值排序元素?
【发布时间】:2020-05-08 23:42:40
【问题描述】:

嘿,我整天都在寻找和寻找。进一步了解我的问题和选项。由于我缺乏理解。

我的一般问题是,我正在尝试根据 JSON 中的值选择行,并通过选择的值对选择进行排序。

我有一个表(元素),有两列:Person 和 Tags。标签包含一个 JSON 数组,其中可以包含多个 JSON 对象。对象总是有“名称”和“排序”。

    +-------------+------------------------------------------------------------------+
    | Person      | tags                                                       
    +-------------+------------------------------------------------------------------+
    | William     | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}]      
    | Anna        | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}]       
    | Michael     | [{"name": "apple", "sort": "2"}]                                     
    +-------------+------------------------------------------------------------------+

理想情况下,我想做的是告诉数据库使用 SELECT * FROM 元素 WHERE 标签(有一个名称为“apple”的对象) ORDER by(匹配对象的排序值);

所以如果我给它“苹果”,它会列出:威廉、迈克尔、安娜。

如果我给它“橙色”,它会列出:安娜,威廉。

我一直在研究在 SELECT(子查询)中包含 SELECT,但我可以找到与 JSON 的正确组合。下面是我得到的最接近的,但我可以说它需要更高级的东西?

SELECT * 
FROM elements 
WHERE JSON_SEARCH( tags, 'one', 'apple', NULL, '$[*].name' ) IS NOT NULL

这将返回所有带有苹果标签的人,但不会根据排序对他们进行排序。

欢迎任何建议,在此先感谢。

【问题讨论】:

    标签: mysql sql json database directory-listing


    【解决方案1】:

    有一个类似的问题here 可能会对您有所帮助。

    您也许可以使用JSON_EXTRACT,但它会变得复杂,因为您存储的是 JSON 数据数组,因此您可能还需要子查询。

    不过,我会提出一个替代解决方案。您是否考虑过跨多个表重构数据库而不是使用 JSON blob?

    您可以有一个专门用于存储标签的表,如下所示:

    +-------------+------------------------------------------------------------------+
    | tagid       | name                                                       
    +-------------+------------------------------------------------------------------+
    | 1           | apple     
    | 2           | orange       
    | 3           | banana                                   
    +-------------+------------------------------------------------------------------+
    

    另一个存放人的表:

    +-------------+------------------------------------------------------------------+
    | id          | name                                                       
    +-------------+------------------------------------------------------------------+
    | 1           | William      
    | 2           | Anna      
    | 3           | Michael                                     
    +-------------+------------------------------------------------------------------+
    

    最后是一张用于存储人和标签之间多对多关系的表格。这也是您可以存储排序顺序的地方:

    +-------------+--------------+-----------+--------------------------------------+
    | id          | personid     | tagid     | sort                                          
    +-------------+--------------+-----------+--------------------------------------+
    | 1           | 1            | 1         | 1
    | 2           | 1            | 2         | 2
    | 3           | 2            | 1         | 3  
    | 4           | 2            | 2         | 1
    | 5           | 3            | 1         | 1                             
    +-------------+--------------+-----------+---------------------------------------+
    

    看起来更像这样的数据库模型将使复杂的查询变得更加简单,并且不需要复杂的子查询,只需连接即可。如果这对您很重要的话,它可能会提高您报告与标签相关的数据的能力。

    【讨论】:

    • 这对我来说是不可能的,实际上我有多个这些 JSON 归档在不同的列中,并且必须为许多关系创建许多表,我认为这会更加整洁。不过感谢您的回复。
    • 很抱歉听到这不是适合您的解决方案。另一种选择可能是在您的应用程序(例如 API)中执行排序,而不是作为查询的一部分?
    【解决方案2】:

    这是一个适合您的“好”查询。您只需将 res.* 更改为 res.name 即可进行查询。

    SELECT res.* FROM (
        SELECT 
            SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'apple')),'.',1) as idx
            ,e.* FROM `elements` AS e ) AS res
     WHERE res.idx IS NOT NULL
     ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
    

    示例

    mysql> select * from elements;
    +----+---------+-------------------------------------------------------------------+
    | id | Person  | tags                                                              |
    +----+---------+-------------------------------------------------------------------+
    |  1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
    |  2 | Anna    | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
    |  3 | Michael | [{"name": "apple", "sort": "2"}]                                  |
    +----+---------+-------------------------------------------------------------------+
    3 rows in set (0.00 sec)
    

    寻找苹果

        mysql> SELECT res.* FROM (
            -> SELECT 
            -> SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'orange')),'.',1) as idx
            -> ,e.* FROM `elements` AS e ) AS res
            ->  WHERE res.idx IS NOT NULL
            ->  ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
    +----+---------+-------------------------------------------------------------------+
    | id | Person  | tags                                                              |
    +----+---------+-------------------------------------------------------------------+
    |  1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
    |  2 | Anna    | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
    |  3 | Michael | [{"name": "apple", "sort": "2"}]                                  |
    +----+---------+-------------------------------------------------------------------+
    3 rows in set (0.00 sec)
    

    找到橙色

    mysql> SELECT res.* FROM (
        -> SELECT 
        -> SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'orange')),'.',1) as idx
        -> ,e.* FROM `elements` AS e ) AS res
        ->  WHERE res.idx IS NOT NULL
        ->  ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
    +------+----+---------+-------------------------------------------------------------------+
    | idx  | id | Person  | tags                                                              |
    +------+----+---------+-------------------------------------------------------------------+
    | $[1] |  2 | Anna    | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
    | $[1] |  1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
    +------+----+---------+-------------------------------------------------------------------+
    2 rows in set (0.01 sec)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-09
      • 2022-01-15
      • 2021-12-17
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 2019-09-01
      相关资源
      最近更新 更多