我是mysql新手,我正在尝试过滤一些数据。我需要更多的整体在一列中,所以我使用了 json 格式。
在chatgpt的帮助下,我可以搜索到很好的结果,但是操作员有问题。
我想在一个查询中使用 AND、OR 和 NOT,但这似乎不起作用。所以我想我可以首先使用 AND 进行过滤,然后使用 OR,最后使用 NOT 进行过滤。 这让我想到了嵌套 json_tables。
但首先,这就是旧查询的样子:
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
在 chatgpt 的帮助下,这就是不起作用的查询的样子:
SELECT id, attributes
FROM (
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
) AS or_filtered,
JSON_TABLE(or_filtered.attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt2 WHERE jt2.value LIKE "sa";
返回
ERROR 1210 (HY000): Incorrect arguments to JSON_TABLE
。
在浏览时我遇到了不同的解决方案,但这似乎仍然不起作用。它使用了
CROSS JOIN
(我的语法不正确吗?):
WITH or_filtered AS (
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
)
SELECT * FROM or_filtered CROSS JOIN JSON_TABLE(or_filtered.attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt2 WHERE jt2.value LIKE "sa";
我不确定为什么 json_table 不想接受来自
or_filtered
表的数据。我也尝试过只使用 attributes
而不是 or_filtered.attributes
,但仍然是同样的错误。
这是一个 MySQL 错误,于 2022 年报告并验证为错误,但尚未修复。请参阅https://bugs.mysql.com/bug.php?id=108365
当您使用派生表子查询,并且启用了衍生_合并的优化器功能时,它会混淆 JSON_TABLE(),因此它不会将该列视为 JSON 类型。
以下四种解决方法中的任何一种都可以使查询运行而不会出现错误:
关闭导致问题的优化器功能。
set optimizer_switch="derived_merge=off";
在子查询中使用
LIMIT
。这显然会阻止优化器功能。
SELECT id, attributes, jt2.value
FROM (
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
LIMIT 100
) AS or_filtered
CROSS JOIN
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt2
WHERE jt2.value LIKE "sa";
将列显式转换为 JSON。
SELECT id, attributes, jt2.value
FROM (
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
) AS or_filtered
CROSS JOIN
JSON_TABLE(CAST(attributes AS JSON), '$[*]' COLUMNS(value TEXT PATH '$')) AS jt2
WHERE jt2.value LIKE "sa";
使用另一个简单的 JSON 表达式将结果强制为 JSON 类型。
SELECT id, attributes, jt2.value
FROM (
SELECT id, attributes FROM files,
JSON_TABLE(attributes, '$[*]' COLUMNS(value TEXT PATH '$')) AS jt
WHERE jt.value LIKE "%a%" OR jt.value LIKE "%f%"
) AS or_filtered
CROSS JOIN
JSON_TABLE(attributes->'$', '$[*]' COLUMNS(value TEXT PATH '$')) AS jt2
WHERE jt2.value LIKE "sa";