我有一个包含 JSON 数据的表,以及一个为每一行提取一组 ID 的语句......
SELECT items.data->"$.matrix[*].id" as ids
FROM items
Run Code Online (Sandbox Code Playgroud)
这会导致类似..
+------------+
| ids |
+------------+
| [1,2,3] |
+------------+
Run Code Online (Sandbox Code Playgroud)
接下来我想从另一个表中选择另一个表的 ID 在数组中,类似于WHERE id IN ('1,2,3')但使用 JSON 数组...
类似的东西...
SELECT * FROM other_items
WHERE id IN (
SELECT items.data->"$.matrix[*].id" FROM items
);
Run Code Online (Sandbox Code Playgroud)
但它需要一些 JSON 魔法,我无法解决......
123*_*4ru 10
从 MySQL 8.0.13 开始,有MEMBER OF运算符,它完全可以满足您的需求。
不过,该查询应该重写为 的形式JOIN:
SELECT o.* FROM other_items o
JOIN items i ON o.id MEMBER OF(i.data->>'$.id')
Run Code Online (Sandbox Code Playgroud)
如果您希望查询具有更好的性能,请考虑在 JSON 列上使用多值索引。
MEMBER OF()下面的例子可以更清楚地解释of 的使用:
CREATE TABLE items ( data JSON );
INSERT INTO items
SET data = '{"id":[1,2,3]}';
Run Code Online (Sandbox Code Playgroud)
这就是确定 JSON 数组中是否存在该值的方法:
SELECT * FROM items
WHERE 3 MEMBER OF(data->>'$.id');
Run Code Online (Sandbox Code Playgroud)
+-------------------+
| data |
+-------------------+
| {"id": [1, 2, 3]} |
+-------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
请注意,与常规比较不同,在这种情况下值的类型很重要。如果以字符串形式传递,则不会匹配:
+-------------------+
| data |
+-------------------+
| {"id": [1, 2, 3]} |
+-------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
Empty set (0.00 sec)
尽管定期比较会返回1:
SELECT * FROM items
WHERE "3" MEMBER OF(data->>'$.id');
Run Code Online (Sandbox Code Playgroud)
+---------+
| 3 = "3" |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
下面是一个完整的答案。您可能需要'use <db_name>;'在脚本顶部添加一条语句。重点是表明 JSON_CONTAINS() 可用于实现所需的连接。
DROP TABLE IF EXISTS `tmp_items`;
DROP TABLE IF EXISTS `tmp_other_items`;
CREATE TABLE `tmp_items` (`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT, `data` json NOT NULL);
CREATE TABLE `tmp_other_items` (`id` int NOT NULL, `text` nvarchar(30) NOT NULL);
INSERT INTO `tmp_items` (`data`)
VALUES
('{ "matrix": [ { "id": 11 }, { "id": 12 }, { "id": 13 } ] }')
, ('{ "matrix": [ { "id": 21 }, { "id": 22 }, { "id": 23 }, { "id": 24 } ] }')
, ('{ "matrix": [ { "id": 31 }, { "id": 32 }, { "id": 33 }, { "id": 34 }, { "id": 35 } ] }')
;
INSERT INTO `tmp_other_items` (`id`, `text`)
VALUES
(11, 'text for 11')
, (12, 'text for 12')
, (13, 'text for 13')
, (14, 'text for 14 - never retrieved')
, (21, 'text for 21')
, (22, 'text for 22')
-- etc...
;
-- Show join working:
SELECT
t1.`id` AS json_table_id
, t2.`id` AS joined_table_id
, t2.`text` AS joined_table_text
FROM
(SELECT st1.id, st1.data->'$.matrix[*].id' as ids FROM `tmp_items` st1) t1
INNER JOIN `tmp_other_items` t2 ON JSON_CONTAINS(t1.ids, CAST(t2.`id` as json), '$')
Run Code Online (Sandbox Code Playgroud)
您应该会看到以下结果:
在 MySQL 中引入 JSON 之前,我使用的是:
你的原始数据:[1,2,3]
将逗号替换为 '][' 后:[1][2][3]
将你的 id 括在“[]”中
然后使用 REVERSE LIKE 而不是 IN:WHERE '[1][2][3]' LIKE
'%[1]%'
回答你的问题:
SELECT * FROM other_items
WHERE
REPLACE(SELECT items.data->"$.matrix[*].id" FROM items, ',', '][')
LIKE CONCAT('%', CONCAT('[', id, ']'), '%')
Run Code Online (Sandbox Code Playgroud)
为什么要换行成“[]”
'[12,23,34]' LIKE '%1%' --> true
'[12,23,34]' LIKE '%12%' --> true
Run Code Online (Sandbox Code Playgroud)
如果换行成'[]'
'[12][23][34]' LIKE '%[1]%' --> false
'[12][23][34]' LIKE '%[12]%' --> true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18704 次 |
| 最近记录: |