MySQL - 按数组中的 JSON 值排序元素?
MySQL - Order elements by JSON value in array?
嘿,我整天都在搜索和寻找。进一步了解我的问题和选择。我缺乏理解。
我的一般问题是,我正在尝试根据 JSON 中的值 SELECT 行,并根据所选值对选择进行排序。
我有一个 table(元素),有两列:Person 和 Tags。标签包含一个 JSON 数组,其中可以包含多个 JSON 对象。对象总是有 "name" 和 "sort"。
+-------------+------------------------------------------------------------------+
| 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 elements WHERE 标签(有一个名称为 "apple" 的对象) ORDER by(对象的排序值它匹配的地方);
所以如果我给它 "apple" 它会列出:William、Michael、Anna。
如果我给它 "orange" 它会列出:Anna, William。
我一直在研究在 SELECTs(子查询)中使用 SELECTs,但我可以找到与 JSON 的正确组合。下面是我得到的最接近的,但我可以看出它需要更高级的东西?
SELECT *
FROM elements
WHERE JSON_SEARCH( tags, 'one', 'apple', NULL, '$[*].name' ) IS NOT NULL
这将 return 所有带有 apple 标签的人,但它不会根据排序对他们进行排序。
欢迎提出任何建议,在此先感谢。
有一个类似的问题here可能会对您有所帮助。
您可以使用 JSON_EXTRACT,但它会变得复杂,因为您要存储一个 JSON 数据数组,因此您可能还需要一个子查询。
不过我会提出替代解决方案。您是否考虑过跨多个 table 重组您的数据库而不是使用 JSON blob?
你可以有一个 table 专用于存储标签,像这样:
+-------------+------------------------------------------------------------------+
| tagid | name
+-------------+------------------------------------------------------------------+
| 1 | apple
| 2 | orange
| 3 | banana
+-------------+------------------------------------------------------------------+
另一个table用来存储人:
+-------------+------------------------------------------------------------------+
| id | name
+-------------+------------------------------------------------------------------+
| 1 | William
| 2 | Anna
| 3 | Michael
+-------------+------------------------------------------------------------------+
最后一个 table 用于存储人与标签之间的多对多关系。这也是您可以存储排序顺序的地方:
+-------------+--------------+-----------+--------------------------------------+
| id | personid | tagid | sort
+-------------+--------------+-----------+--------------------------------------+
| 1 | 1 | 1 | 1
| 2 | 1 | 2 | 2
| 3 | 2 | 1 | 3
| 4 | 2 | 2 | 1
| 5 | 3 | 1 | 1
+-------------+--------------+-----------+---------------------------------------+
看起来更像这样的数据库模型将使复杂的查询变得更加简单,并且不需要复杂的子查询,只需要连接。如果这对您很重要,它可能会提高您报告与标签相关的数据的能力。
这里有一个适合您的 "nice" 查询。您只需将查询的 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)
嘿,我整天都在搜索和寻找。进一步了解我的问题和选择。我缺乏理解。
我的一般问题是,我正在尝试根据 JSON 中的值 SELECT 行,并根据所选值对选择进行排序。
我有一个 table(元素),有两列:Person 和 Tags。标签包含一个 JSON 数组,其中可以包含多个 JSON 对象。对象总是有 "name" 和 "sort"。
+-------------+------------------------------------------------------------------+
| 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 elements WHERE 标签(有一个名称为 "apple" 的对象) ORDER by(对象的排序值它匹配的地方);
所以如果我给它 "apple" 它会列出:William、Michael、Anna。
如果我给它 "orange" 它会列出:Anna, William。
我一直在研究在 SELECTs(子查询)中使用 SELECTs,但我可以找到与 JSON 的正确组合。下面是我得到的最接近的,但我可以看出它需要更高级的东西?
SELECT *
FROM elements
WHERE JSON_SEARCH( tags, 'one', 'apple', NULL, '$[*].name' ) IS NOT NULL
这将 return 所有带有 apple 标签的人,但它不会根据排序对他们进行排序。
欢迎提出任何建议,在此先感谢。
有一个类似的问题here可能会对您有所帮助。
您可以使用 JSON_EXTRACT,但它会变得复杂,因为您要存储一个 JSON 数据数组,因此您可能还需要一个子查询。
不过我会提出替代解决方案。您是否考虑过跨多个 table 重组您的数据库而不是使用 JSON blob?
你可以有一个 table 专用于存储标签,像这样:
+-------------+------------------------------------------------------------------+
| tagid | name
+-------------+------------------------------------------------------------------+
| 1 | apple
| 2 | orange
| 3 | banana
+-------------+------------------------------------------------------------------+
另一个table用来存储人:
+-------------+------------------------------------------------------------------+
| id | name
+-------------+------------------------------------------------------------------+
| 1 | William
| 2 | Anna
| 3 | Michael
+-------------+------------------------------------------------------------------+
最后一个 table 用于存储人与标签之间的多对多关系。这也是您可以存储排序顺序的地方:
+-------------+--------------+-----------+--------------------------------------+
| id | personid | tagid | sort
+-------------+--------------+-----------+--------------------------------------+
| 1 | 1 | 1 | 1
| 2 | 1 | 2 | 2
| 3 | 2 | 1 | 3
| 4 | 2 | 2 | 1
| 5 | 3 | 1 | 1
+-------------+--------------+-----------+---------------------------------------+
看起来更像这样的数据库模型将使复杂的查询变得更加简单,并且不需要复杂的子查询,只需要连接。如果这对您很重要,它可能会提高您报告与标签相关的数据的能力。
这里有一个适合您的 "nice" 查询。您只需将查询的 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)