MySQL 5 从 json 数组中的整数连接
MySQL 5 join from integers in json array
有什么方法可以用 MySQL 5 完成这个吗?
我有两个 tables users 和 roles
用户
desc users;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| data | json | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
select * from users;
+------+------------------------------------+
| id | data |
+------+------------------------------------+
| 1 | {"name": "cat", "roleIds": [2, 3]} |
| 2 | {"name": "dog", "roleIds": [1, 4]} |
| 3 | {"name": "mouse", "roleIds": [5]} |
+------+------------------------------------+
3 rows in set (0.00 sec)
角色
desc roles;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| role_id | int(11) | NO | | 0 | |
| name | varchar(64) | NO | | NULL | |
+---------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
select * from roles;
+---------+-------------+
| role_id | name |
+---------+-------------+
| 1 | Admin |
| 2 | Supervisor |
| 3 | Provisioner |
| 4 | Operator |
| 5 | Relief |
+---------+-------------+
5 rows in set (0.01 sec)
我想用角色名称修改用户 table 中的 json 数据
结果看起来像这样
+------+------------------------------------------------------------------------------+
| id | data |
+------+------------------------------------------------------------------------------+
| 1 | {"name": "cat", "roleIds": [2, 3], "roleNames": "[Supervisor, Provisioner]"} |
| 2 | {"name": "dog", "roleIds": [1, 4], "roleNames": "[Admin, Operator]"} |
| 3 | {"name": "mouse", "roleIds": [5], "roleNames": "[Relief]"} |
+------+------------------------------------------------------------------------------+
这是使用 json_set()
、json_contains()
和 json_arrayagg()
的一种方法,它们都在 MySQL 5.7 中可用(后者在版本 5.7.22 中引入) :
select u.id,
json_set(
u.data,
'$.roleNames', (
select json_arrayagg(r.name)
from roles r
where json_contains(u.data, cast(r.role_id as json), '$.roleIds')
)
) as data
from users u
id
data
1
{"name": "cat", "roleIds": [2, 3], "roleNames": ["Supervisor", "Provisioner"]}
2
{"name": "dog", "roleIds": [1, 4], "roleNames": ["Admin", "Operator"]}
3
{"name": "mouse", "roleIds": [5], "roleNames": ["Relief"]}
需要指出的是,MySQL 不保证元素在 json_arrayagg()
生成的数组中出现的顺序。这是我们必须接受的当前数据库版本的限制。
有什么方法可以用 MySQL 5 完成这个吗?
我有两个 tables users 和 roles
用户
desc users;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| data | json | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
select * from users;
+------+------------------------------------+
| id | data |
+------+------------------------------------+
| 1 | {"name": "cat", "roleIds": [2, 3]} |
| 2 | {"name": "dog", "roleIds": [1, 4]} |
| 3 | {"name": "mouse", "roleIds": [5]} |
+------+------------------------------------+
3 rows in set (0.00 sec)
角色
desc roles;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| role_id | int(11) | NO | | 0 | |
| name | varchar(64) | NO | | NULL | |
+---------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
select * from roles;
+---------+-------------+
| role_id | name |
+---------+-------------+
| 1 | Admin |
| 2 | Supervisor |
| 3 | Provisioner |
| 4 | Operator |
| 5 | Relief |
+---------+-------------+
5 rows in set (0.01 sec)
我想用角色名称修改用户 table 中的 json 数据 结果看起来像这样
+------+------------------------------------------------------------------------------+
| id | data |
+------+------------------------------------------------------------------------------+
| 1 | {"name": "cat", "roleIds": [2, 3], "roleNames": "[Supervisor, Provisioner]"} |
| 2 | {"name": "dog", "roleIds": [1, 4], "roleNames": "[Admin, Operator]"} |
| 3 | {"name": "mouse", "roleIds": [5], "roleNames": "[Relief]"} |
+------+------------------------------------------------------------------------------+
这是使用 json_set()
、json_contains()
和 json_arrayagg()
的一种方法,它们都在 MySQL 5.7 中可用(后者在版本 5.7.22 中引入) :
select u.id,
json_set(
u.data,
'$.roleNames', (
select json_arrayagg(r.name)
from roles r
where json_contains(u.data, cast(r.role_id as json), '$.roleIds')
)
) as data
from users u
id | data |
---|---|
1 | {"name": "cat", "roleIds": [2, 3], "roleNames": ["Supervisor", "Provisioner"]} |
2 | {"name": "dog", "roleIds": [1, 4], "roleNames": ["Admin", "Operator"]} |
3 | {"name": "mouse", "roleIds": [5], "roleNames": ["Relief"]} |
需要指出的是,MySQL 不保证元素在 json_arrayagg()
生成的数组中出现的顺序。这是我们必须接受的当前数据库版本的限制。