如何在MySQL dB 中搜索一个JSON 以满足要求的条件?
How to search a JSON in MySQL dB to satisfy the required condition?
假设我有一个 MySQL dB 的数据列表如下:
+----+------------+-------------------------------------------+
| id | index_date | token_json |
+----+------------+-------------------------------------------+
| 0 | 20200902_0 | [{"tk": [1, 2], "amt": [20, 49]}] |
| 1 | 20200902_1 | [{"tk": [4, 3], "amt": [10, 39]} |
| 2 | 20200902_2 | [{"tk": [7, 4], "amt": [12, 29]} |
| 3 | 20200902_3 | [{"tk": [8, 7, 6], "amt": [13, 19, 19]} |
| 4 | 20200902_4 | [{"tk": [9, 6], "amt": [25, 59] |
+----+------------+-------------------------------------------+
token_json字段实际上是存储了一个JSON字符串。现在,我想获取此数据的子集,条件为 "sub_token" > 5
。
输出子集应如下所示:
+----+------------+-------------------------------------------+
| id | index_date | token_json |
+----+------------+-------------------------------------------+
| 2 | 20200902_2 | [{"tk": [7, 4], "amt": [12, 29]} |
| 3 | 20200902_3 | [{"tk": [8, 7, 6], "amt": [13, 19, 19]} |
| 4 | 20200902_4 | [{"tk": [9, 6], "amt": [25, 59] |
+----+------------+-------------------------------------------+
我尝试了下面的命令但不起作用。
SELECT * from my_table
WHERE JSON_EXTRACT(token_json, '$.tk') > 5;
谁能指导我如何获得这样的子集?
我的 MySQL 版本是 5.7.19-17-57-log
如果你的数据库版本是8+,那么你可以使用JSON_TABLE()
函数作为
WITH t(arr, id, token_json) AS
(
SELECT JSON_EXTRACT(token_json, '$[*].tk'), id, token_json FROM my_table t
)
SELECT id, token_json
FROM t
WHERE EXISTS
( SELECT 1
FROM t AS t2
JOIN JSON_TABLE( CAST( arr AS JSON ), "$[*]"
COLUMNS(
val INT PATH "$"
)
) js
WHERE t2.token_json = t.token_json
AND val > 5 )
Update : 考虑到你的数据库版本是5.7,你可以使用如下方法:
SELECT id, token_json
FROM my_table
WHERE id IN
(SELECT id
FROM (SELECT JSON_EXTRACT(JSON_EXTRACT(token_json, '$[*].tk'),
CONCAT('$[', i, ']')) AS val,
t.*
FROM my_table t
JOIN (SELECT @i := @i + 1 AS i
FROM information_schema.tables i
JOIN (SELECT @i := -1) AS iter
WHERE @i < (SELECT MAX(JSON_LENGTH(token_json))
FROM my_table) - 1) AS t) AS tt
WHERE val > 5)
更新 2:如果您将值转换为这种格式(如上一条评论所述);
+----+------------+---------------------------------------------+
| id | index_date | token_json |
+----+------------+---------------------------------------------+
| 0 | 20200902_0 | {"tk": [1,2], "amt": [20,49]} |
| 1 | 20200902_1 | {"tk": [4,3,2], "amt": [10,39,19]} |
| 2 | 20200902_2 | {"tk": [7,4], "amt": [12,29]} |
| 3 | 20200902_3 | {"tk": [8,7,6], "amt": [13,19,19]} |
| 4 | 20200902_4 | {"tk": [9,6], "amt": [25,59]} |
+----+------------+---------------------------------------------+
然后你可以使用(对于5.7):
SELECT id, token_json
FROM my_table
WHERE id IN
(SELECT id
FROM (SELECT JSON_EXTRACT(JSON_EXTRACT(token_json, '$.tk'),
CONCAT('$[', i, ']')) AS elm,
t.*
FROM my_table t
JOIN (SELECT @i := @i + 1 AS i
FROM information_schema.tables i
JOIN (SELECT @i := -1) AS iter
WHERE @i < (SELECT MAX(JSON_LENGTH(token_json))
FROM my_table) - 1) AS t) AS tt
WHERE elm > 5)
你可以使用(对于 8.0 ):
WITH t(arr, id, token_json) AS
(
SELECT JSON_EXTRACT(token_json, '$.tk') AS arr, id, token_json FROM my_table t
)
SELECT id, token_json
FROM t
WHERE EXISTS
( SELECT 1
FROM t AS t2
JOIN JSON_TABLE( CAST( arr AS JSON ), "$[*]"
COLUMNS(
val INT PATH "$"
)
) js
WHERE t2.token_json = t.token_json
AND val > 5 )
假设我有一个 MySQL dB 的数据列表如下:
+----+------------+-------------------------------------------+
| id | index_date | token_json |
+----+------------+-------------------------------------------+
| 0 | 20200902_0 | [{"tk": [1, 2], "amt": [20, 49]}] |
| 1 | 20200902_1 | [{"tk": [4, 3], "amt": [10, 39]} |
| 2 | 20200902_2 | [{"tk": [7, 4], "amt": [12, 29]} |
| 3 | 20200902_3 | [{"tk": [8, 7, 6], "amt": [13, 19, 19]} |
| 4 | 20200902_4 | [{"tk": [9, 6], "amt": [25, 59] |
+----+------------+-------------------------------------------+
token_json字段实际上是存储了一个JSON字符串。现在,我想获取此数据的子集,条件为 "sub_token" > 5
。
输出子集应如下所示:
+----+------------+-------------------------------------------+
| id | index_date | token_json |
+----+------------+-------------------------------------------+
| 2 | 20200902_2 | [{"tk": [7, 4], "amt": [12, 29]} |
| 3 | 20200902_3 | [{"tk": [8, 7, 6], "amt": [13, 19, 19]} |
| 4 | 20200902_4 | [{"tk": [9, 6], "amt": [25, 59] |
+----+------------+-------------------------------------------+
我尝试了下面的命令但不起作用。
SELECT * from my_table
WHERE JSON_EXTRACT(token_json, '$.tk') > 5;
谁能指导我如何获得这样的子集? 我的 MySQL 版本是 5.7.19-17-57-log
如果你的数据库版本是8+,那么你可以使用JSON_TABLE()
函数作为
WITH t(arr, id, token_json) AS
(
SELECT JSON_EXTRACT(token_json, '$[*].tk'), id, token_json FROM my_table t
)
SELECT id, token_json
FROM t
WHERE EXISTS
( SELECT 1
FROM t AS t2
JOIN JSON_TABLE( CAST( arr AS JSON ), "$[*]"
COLUMNS(
val INT PATH "$"
)
) js
WHERE t2.token_json = t.token_json
AND val > 5 )
Update : 考虑到你的数据库版本是5.7,你可以使用如下方法:
SELECT id, token_json
FROM my_table
WHERE id IN
(SELECT id
FROM (SELECT JSON_EXTRACT(JSON_EXTRACT(token_json, '$[*].tk'),
CONCAT('$[', i, ']')) AS val,
t.*
FROM my_table t
JOIN (SELECT @i := @i + 1 AS i
FROM information_schema.tables i
JOIN (SELECT @i := -1) AS iter
WHERE @i < (SELECT MAX(JSON_LENGTH(token_json))
FROM my_table) - 1) AS t) AS tt
WHERE val > 5)
更新 2:如果您将值转换为这种格式(如上一条评论所述);
+----+------------+---------------------------------------------+
| id | index_date | token_json |
+----+------------+---------------------------------------------+
| 0 | 20200902_0 | {"tk": [1,2], "amt": [20,49]} |
| 1 | 20200902_1 | {"tk": [4,3,2], "amt": [10,39,19]} |
| 2 | 20200902_2 | {"tk": [7,4], "amt": [12,29]} |
| 3 | 20200902_3 | {"tk": [8,7,6], "amt": [13,19,19]} |
| 4 | 20200902_4 | {"tk": [9,6], "amt": [25,59]} |
+----+------------+---------------------------------------------+
然后你可以使用(对于5.7):
SELECT id, token_json
FROM my_table
WHERE id IN
(SELECT id
FROM (SELECT JSON_EXTRACT(JSON_EXTRACT(token_json, '$.tk'),
CONCAT('$[', i, ']')) AS elm,
t.*
FROM my_table t
JOIN (SELECT @i := @i + 1 AS i
FROM information_schema.tables i
JOIN (SELECT @i := -1) AS iter
WHERE @i < (SELECT MAX(JSON_LENGTH(token_json))
FROM my_table) - 1) AS t) AS tt
WHERE elm > 5)
你可以使用(对于 8.0 ):
WITH t(arr, id, token_json) AS
(
SELECT JSON_EXTRACT(token_json, '$.tk') AS arr, id, token_json FROM my_table t
)
SELECT id, token_json
FROM t
WHERE EXISTS
( SELECT 1
FROM t AS t2
JOIN JSON_TABLE( CAST( arr AS JSON ), "$[*]"
COLUMNS(
val INT PATH "$"
)
) js
WHERE t2.token_json = t.token_json
AND val > 5 )