如何在MySQL 5.7上模拟JSON_重叠函数?
我有两个来自不同表的列,它们保存JSON格式的数据。两列中存储的数据都是数组。例如:如何在MySQL 5.7上模拟JSON_重叠函数?,mysql,Mysql,我有两个来自不同表的列,它们保存JSON格式的数据。两列中存储的数据都是数组。例如: 用户 +----+------------------+ | id | options | +----+------------------+ | 1 | ["AB","CD","XY"] | | 2 | ["CD","GH"] | +----+------------------+ +----+-------------+ | id | options | +----
用户
+----+------------------+
| id | options |
+----+------------------+
| 1 | ["AB","CD","XY"] |
| 2 | ["CD","GH"] |
+----+------------------+
+----+-------------+
| id | options |
+----+-------------+
| 10 | ["CD","EF"] |
| 11 | ["GH","XY"] |
| 12 | ["GH"] |
+----+-------------+
项目
+----+------------------+
| id | options |
+----+------------------+
| 1 | ["AB","CD","XY"] |
| 2 | ["CD","GH"] |
+----+------------------+
+----+-------------+
| id | options |
+----+-------------+
| 10 | ["CD","EF"] |
| 11 | ["GH","XY"] |
| 12 | ["GH"] |
+----+-------------+
我想编写一个查询,使用选项
列执行匹配,返回用户
中与项
中给定行匹配的所有行。规则是,如果两行中都存在数组中的任何值,则它们是匹配的。示例:用户1将匹配项目10(因为CD
选项)和项目11(因为XY
选项);用户2将匹配项目10、11和12,因为它们都有CD
或GH
查看MySQL文档,我发现它确实做到了这一点。但是,我运行的是MySQL 5.7,该函数仅从8.0.17开始提供。网络上也没有太多关于这个功能的讨论
如何在查询中模拟MySQL 5.7上的JSON\u重叠
行为
编辑:不幸的是,升级到MySQL 8不是一个选项,因为我们在生产环境中运行MariaDB,它也没有该功能
如何在MySQL 5.7上模拟JSON_重叠函数
编辑:不幸的是,升级到MySQL 8不是一个选项,因为我们在生产环境中运行MariaDB,它也没有这个功能
像草莓一样受到警告,建议升级更容易
SELECT
*
FROM (
SELECT
items.id
, JSON_UNQUOTE(
JSON_EXTRACT(items.options, CONCAT('$[', number_generator.number , ']'))
) AS json_options
FROM (
SELECT
@items_row := @items_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 @items_row := -1
) init_user_params
) AS number_generator
CROSS JOIN (
SELECT
items.id
, items.options
, JSON_LENGTH(items.options) AS json_array_length
FROM
items
) AS items
WHERE
number BETWEEN 0 AND json_array_length - 1
) AS items
INNER JOIN (
SELECT
users.id
, JSON_UNQUOTE(
JSON_EXTRACT(users.options, CONCAT('$[', number_generator.number , ']'))
) AS json_options
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
users.id
, users.options
, JSON_LENGTH(users.options) AS json_array_length
FROM
users
) AS users
WHERE
number BETWEEN 0 AND json_array_length - 1
) AS users
USING(json_options)
现在,这是不可能的。你还是自找的,让我们玩一玩吧。
我过去发布了一些来模拟MySQL的8JSON_TABLE()
,为什么我要提到这一点?因为我使用此方法模拟MySQL的8个JSON_重叠
,将模拟JSON_TABLE()
的两个结果集简单地连接到最终的结果集
这将生成下面的查询(请原谅格式)
查询
SELECT
*
FROM (
SELECT
items.id
, JSON_UNQUOTE(
JSON_EXTRACT(items.options, CONCAT('$[', number_generator.number , ']'))
) AS json_options
FROM (
SELECT
@items_row := @items_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 @items_row := -1
) init_user_params
) AS number_generator
CROSS JOIN (
SELECT
items.id
, items.options
, JSON_LENGTH(items.options) AS json_array_length
FROM
items
) AS items
WHERE
number BETWEEN 0 AND json_array_length - 1
) AS items
INNER JOIN (
SELECT
users.id
, JSON_UNQUOTE(
JSON_EXTRACT(users.options, CONCAT('$[', number_generator.number , ']'))
) AS json_options
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
users.id
, users.options
, JSON_LENGTH(users.options) AS json_array_length
FROM
users
) AS users
WHERE
number BETWEEN 0 AND json_array_length - 1
) AS users
USING(json_options)
结果
| json_options | id | id |
| ------------ | --- | --- |
| CD | 10 | 2 |
| CD | 10 | 1 |
| GH | 11 | 2 |
| GH | 12 | 2 |
| XY | 11 | 1 |
请参见simpler@Strawberry我想有人会建议这样做,所以我只是编辑了这个问题,告诉大家我们在生产中运行MariaDB。但无论如何,还是要谢谢你。我发布了一个答案,我相信它也应该适用于MariaDB~10.2+(我相信)…嘿!尽管这是一个巨大的疑问,但它却像一个魅力!谢谢“尽管这是一个巨大的疑问,”很抱歉,我从未说过这很容易@GustavoStraube,希望你能找到它的工作原理。。