如何通过 MySQL 中的 json 整数数组列中的 id 获取相关项目
How to get related items by id inside of json integer array column in MySQL
我的目标是如何获得在 json 数组中具有引用的列与其他列之间的关系。以简化的方式,我有两个 tables:
table_a
| id | references |
|-----|------------|
| 1 | "[1,3]" |
| 2 | "[2,3]" |
其引用是 json 整数数组和 table b
table_b
| id | name |
|-----|----------|
| 1 | "item 1" |
| 2 | "item 2" |
| 3 | "item 3" |
所以,我想获取 table B 的所有项目与 table A 的项目相关的 id,例如 1,它们的 id 在列引用整数数组(如 json).
像这样:
|-----|----------|
| 1 | "item 1" |
| 3 | "item 3" |
我一直在尝试通过 json_contains、json_extract、 来实现这一目标json_search,等等,来自 docs,我认为问题在于匹配 json 整数数组中的值的方式。
例如:
SELECT JSON_SEARCH((select references from table_a where id=1), 'one', '3');
必须 return 一些东西,但总是 return NULL
我不明白。我也试过 3
不带引号。
¿有什么想法吗?
我当前的 MySQL 版本是 5.7.25
提前致谢。
要重现的最少代码:
select version();
CREATE TABLE `table_a` (
`id` int(11) NOT NULL,
`references` json NULL
);
CREATE TABLE `table_b` (
`id` int(11) NOT NULL,
`name` text NULL
);
INSERT INTO `table_a` (`id`, `references`) VALUES
(1, '\"[1,3]\"'),
(2, '\"[2,3]\"');
INSERT INTO `table_b` (`id`, `name`) VALUES
(1, 'item_1'),
(2, 'item_2'),
(3, 'item_3');
SELECT * from table_a;
SELECT * from table_b;
select `references` from table_a where id=1;
SELECT JSON_SEARCH((select `references` from table_a where id=1), 'one', '3');
要测试的沙盒:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=ac557666852fa94e77fdf87158c9abe0
不正确(但通过 JSON_VALID 函数检查成功)JSON.
解决方案太可怕了:
SELECT table_b.*
FROM table_a, table_b
WHERE table_a.id = 1
AND JSON_SEARCH(REPLACE(REPLACE(REPLACE(REPLACE(table_a.references, '"', ''), '[', '["'), ']', '"]'), ',', '","'), 'one', table_b.id) IS NOT NULL
fiddle 以及一些解释问题的额外查询。
您可以使用下一个查询作为解决方案:
select
table_a.*,
table_b.*
from table_a
join table_b on JSON_CONTAINS(
CAST(TRIM('"' FROM `references`) as JSON),
CAST(table_b.id as JSON)
)
where table_a.id=2;
因为你的references
字段是无效的JSON类型你需要把它转换成JSON然后才能使用JSON_CONTAINS函数
试一试here
您可以先去掉包裹数组的引号,然后将生成的整数与 item_
子字符串连接起来,同时使用辅助子查询,其中一个生成行以便连续获取数组的每个成员比如
SELECT b.*
FROM
(
SELECT @i := @i + 1 AS rn,
CONCAT('item_',JSON_EXTRACT(JSON_UNQUOTE(`references`),
CONCAT('$[',@i-1,']'))) AS name
FROM information_schema.tables
CROSS JOIN `table_a` AS a
CROSS JOIN (SELECT @i := 0) r
WHERE @i < JSON_LENGTH(JSON_UNQUOTE(`references`)) ) AS a
JOIN `table_b` AS b
ON b.`name` = a.name
我的目标是如何获得在 json 数组中具有引用的列与其他列之间的关系。以简化的方式,我有两个 tables:
table_a
| id | references |
|-----|------------|
| 1 | "[1,3]" |
| 2 | "[2,3]" |
其引用是 json 整数数组和 table b
table_b
| id | name |
|-----|----------|
| 1 | "item 1" |
| 2 | "item 2" |
| 3 | "item 3" |
所以,我想获取 table B 的所有项目与 table A 的项目相关的 id,例如 1,它们的 id 在列引用整数数组(如 json).
像这样:
|-----|----------|
| 1 | "item 1" |
| 3 | "item 3" |
我一直在尝试通过 json_contains、json_extract、 来实现这一目标json_search,等等,来自 docs,我认为问题在于匹配 json 整数数组中的值的方式。
例如:
SELECT JSON_SEARCH((select references from table_a where id=1), 'one', '3');
必须 return 一些东西,但总是 return NULL
我不明白。我也试过 3
不带引号。
¿有什么想法吗?
我当前的 MySQL 版本是 5.7.25
提前致谢。
要重现的最少代码:
select version();
CREATE TABLE `table_a` (
`id` int(11) NOT NULL,
`references` json NULL
);
CREATE TABLE `table_b` (
`id` int(11) NOT NULL,
`name` text NULL
);
INSERT INTO `table_a` (`id`, `references`) VALUES
(1, '\"[1,3]\"'),
(2, '\"[2,3]\"');
INSERT INTO `table_b` (`id`, `name`) VALUES
(1, 'item_1'),
(2, 'item_2'),
(3, 'item_3');
SELECT * from table_a;
SELECT * from table_b;
select `references` from table_a where id=1;
SELECT JSON_SEARCH((select `references` from table_a where id=1), 'one', '3');
要测试的沙盒:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=ac557666852fa94e77fdf87158c9abe0
不正确(但通过 JSON_VALID 函数检查成功)JSON.
解决方案太可怕了:
SELECT table_b.*
FROM table_a, table_b
WHERE table_a.id = 1
AND JSON_SEARCH(REPLACE(REPLACE(REPLACE(REPLACE(table_a.references, '"', ''), '[', '["'), ']', '"]'), ',', '","'), 'one', table_b.id) IS NOT NULL
fiddle 以及一些解释问题的额外查询。
您可以使用下一个查询作为解决方案:
select
table_a.*,
table_b.*
from table_a
join table_b on JSON_CONTAINS(
CAST(TRIM('"' FROM `references`) as JSON),
CAST(table_b.id as JSON)
)
where table_a.id=2;
因为你的references
字段是无效的JSON类型你需要把它转换成JSON然后才能使用JSON_CONTAINS函数
试一试here
您可以先去掉包裹数组的引号,然后将生成的整数与 item_
子字符串连接起来,同时使用辅助子查询,其中一个生成行以便连续获取数组的每个成员比如
SELECT b.*
FROM
(
SELECT @i := @i + 1 AS rn,
CONCAT('item_',JSON_EXTRACT(JSON_UNQUOTE(`references`),
CONCAT('$[',@i-1,']'))) AS name
FROM information_schema.tables
CROSS JOIN `table_a` AS a
CROSS JOIN (SELECT @i := 0) r
WHERE @i < JSON_LENGTH(JSON_UNQUOTE(`references`)) ) AS a
JOIN `table_b` AS b
ON b.`name` = a.name