MYSQL5.7模拟MYSQL8.0的JSON_OVERLAPS替代方案
我有来自不同表的两列,它们保存 JSON 格式的数据。两列中存储的数据都是数组。示例:
用户
+----+------------------+
| id | roleIds |
+----+------------------+
| 1 | ["AB","CD","XY"] |
| 2 | ["CD","GH"] |
+----+------------------+
权限
+----+-------------+
| id | roleIds |
+----+-------------+
| 10 | ["CD","EF"] |
| 11 | ["GH","XY"] |
| 12 | ["GH"] |
+----+-------------+
我想编写一个查询,返回与 items 中给定行匹配的 users 中的所有行,并使用 permission 列来执行比赛。规则是如果数组中的任何值都出现在两行中,则它们是匹配的。示例:用户 1 将匹配项目 10(因为 CD 选项)和 11(因为 XY 选项);用户 2 将匹配项目 10、11 和 12,因为它们都具有 CD 或 GH。
查看 MySQL 文档我发现 JSON_OVERLAPS正是这样做的。但是,我运行的是 MySQL 5.7,该功能仅从 8.0.17 开始可用。网络上也没有太多关于此功能的讨论。
如何在查询中模拟 MySQL 5.7 上的 JSON_OVERLAPS 行为?
编辑:不幸的是,升级到 MySQL 8 不是一个选择,因为我们在生产环境中运行 MariaDB,它也没有该功能。
MYSQL5.7模拟MYSQL8.0的JSON_OVERLAPS替代方案
SELECT * FROM (
SELECT permission.id,permission.alias,JSON_UNQUOTE(JSON_EXTRACT(permission.roleIds,CONCAT('$[', number_generator.number , ']'))) AS json_rid
FROM (
SELECT @permission_row := @permission_row + 1 AS number
FROM (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) row1
CROSS JOIN (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) row2
CROSS JOIN (SELECT @permission_row := -1) init_user_params
) AS number_generator
CROSS JOIN (SELECT permission.id,permission.alias, permission.roleIds, JSON_LENGTH(permission.roleIds) AS json_array_length FROM permission) AS permissionWHERE number BETWEEN 0 AND json_array_length - 1
) AS permission
INNER JOIN (
SELECT user.id,JSON_UNQUOTE(JSON_EXTRACT(user.roleIds,CONCAT('$[', number_generator.number , ']'))) AS json_rid
FROM (
SELECT @users_row := @users_row + 1 AS number
FROM (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) row1
CROSS JOIN (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) row2
CROSS JOIN (SELECT @users_row := -1) init_user_params
) AS number_generator
CROSS JOIN (SELECT user.id,user.roleIds,JSON_LENGTH(user.roleIds) AS json_array_length FROM user) AS user
WHERE number BETWEEN 0 AND json_array_length - 1
) AS user
USING(json_rid)
回复
要发表评论,您必须先登录。