如何通过 id 在 MySQL 中的 json 整数数组列中获取相关项目

Posted

技术标签:

【中文标题】如何通过 id 在 MySQL 中的 json 整数数组列中获取相关项目【英文标题】:How to get related items by id inside of json integer array column in MySQL 【发布时间】:2021-02-22 03:51:02 【问题描述】:

我的目标是如何获取在 json 数组中有引用的列与其他列之间的关系。简单来说,我有两张表:

table_a
| id  | references |
|-----|------------|
| 1   |  "[1,3]"   |
| 2   |  "[2,3]"   |

其引用是一个 json 整数数组和表 b

table_b
| id  | name     |
|-----|----------|
| 1   | "item 1" |
| 2   | "item 2" |
| 3   | "item 3" |

所以,我想获取表 B 的所有项目,这些项目与表 A 的 id 项目相关,例如 1,其 id 在列引用整数数组(如 json)中。

类似这样的:

|-----|----------|
| 1   | "item 1" |
| 3   | "item 3" |

我一直在尝试使用来自docs 的 json_containsjson_extractjson_search 等来实现这一点,我认为问题在于以匹配 json 整数数组中的值的方式。

例如:

SELECT JSON_SEARCH((select references from table_a where id=1), 'one', '3');

必须返回一些东西,但总是返回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

【问题讨论】:

将源数据显示为 CREATE TABLE + INSERT INTO 脚本(或创建在线小提琴)。将所需的输出显示为格式化的文本表格。 为什么使用 json 数组而不是常规的规范化模式? @Akina 我已经更新了。 @Strawberry 我知道。但这是现在数据模型的要求。如果达不到,我会重构它。 我没有看到想要的结果.. 【参考方案1】:

不正确(但通过 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 带有一些解释问题的附加查询。

【讨论】:

【参考方案2】:

您可以使用下一个查询作为解决方案:

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

【讨论】:

【参考方案3】:

您可以先去掉包裹数组的引号,然后将生成的整数与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

Demo

【讨论】:

以上是关于如何通过 id 在 MySQL 中的 json 整数数组列中获取相关项目的主要内容,如果未能解决你的问题,请参考以下文章

java通过jdbc查找数据,查出id值,如何通过整型变量存储这个id值

如何在 MySQL 中将元素推送到 JSON

如何在单个查询中返回 node.js mysql 中的嵌套 json

通过 PHP 将来自 MySQL 的 JSON 解码为 SwiftUI 中的复杂结构

如何在 MySQL 中的 JSON 数组内的元素中提取特定属性的所有值?

如何计算mysql中的json项目