Как выполнить MySQL "IN" запрос условия с JSON_EXTRACT? - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть таблица, подобная следующей:

CREATE TABLE `foo` (
  `foo_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `data` json DEFAULT NULL,
  `data_type` int(11) NOT NULL,
  `data_status` int(11) NOT NULL,
  PRIMARY KEY (`foo_id`)
);

вставить некоторые данные

insert into foo(data, data_type, data_status) values ('{\"id\": \"FOO\", \"code\": \"FOO\"}', 1, 1);
insert into foo(data, data_type, data_status) values ('{\"id\": \"BAR\", \"code\": \"BAR\"}', 1, 1);
insert into foo(data, data_type, data_status) values ('{\"id\": \"BAZ\", \"code\": \"BAZ\"}', 1, 1);

показать содержимое таблицы:

mysql> select * from foo;
+--------+------------------------------+-----------+-------------+
| foo_id | data                         | data_type | data_status |
+--------+------------------------------+-----------+-------------+
|      1 | {"id": "FOO", "code": "FOO"} |         1 |           1 |
|      2 | {"id": "BAR", "code": "BAR"} |         1 |           1 |
|      3 | {"id": "BAZ", "code": "BAZ"} |         1 |           1 |
+--------+------------------------------+-----------+-------------+
3 rows in set (0.01 sec)

Этот запрос работает:

select f.data, f.data_type, f.data_status
from foo f
where (JSON_EXTRACT(f.data, '$.code') in ('FOO'))
   and (f.data_type in (1)) 
   and (f.data_status in (1));

+------------------------------+-----------+-------------+
| data                         | data_type | data_status |
+------------------------------+-----------+-------------+
| {"id": "FOO", "code": "FOO"} |         1 |           1 |
+------------------------------+-----------+-------------+
1 row in set (0.00 sec)

Это тоже:

select f.data, f.data_type, f.data_status
from foo f
where (JSON_EXTRACT(f.data, '$.code') in ('BAR'))
   and (f.data_type in (1)) 
   and (f.data_status in (1));

+------------------------------+-----------+-------------+
| data                         | data_type | data_status |
+------------------------------+-----------+-------------+
| {"id": "BAR", "code": "BAR"} |         1 |           1 |
+------------------------------+-----------+-------------+

Однако это не так ...

select f.data, f.data_type, f.data_status
from foo f
where (JSON_EXTRACT(f.data, '$.code') in ('FOO','BAR'))
   and (f.data_type in (1)) 
   and (f.data_status in (1));

Empty set, 1 warning (0.00 sec)

Как заставить работать третий запрос?

1 Ответ

0 голосов
/ 01 апреля 2020

Я заметил, что в последнем запросе было предупреждение

Empty set, 1 warning (0.00 sec)

...

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------------------------------------------+
| Level   | Code | Message                                                                           |
+---------+------+-----------------------------------------------------------------------------------+
| Warning | 1235 | This version of MySQL doesn't yet support 'comparison of JSON in the IN operator' |
+---------+------+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> 

Однако это предупреждение привело меня к этому сообщению

https://bugs.mysql.com/bug.php?id=93800

Таким образом, изменяя запрос, чтобы заключить аргументы IN в кавычки, он работает

select f.data, f.data_type, f.data_status 
from foo f 
where (JSON_EXTRACT(f.data, '$.code') in ('"FOO"','"BAR"'))    
and (f.data_type in (1))     
and (f.data_status in (1));
+------------------------------+-----------+-------------+
| data                         | data_type | data_status |
+------------------------------+-----------+-------------+
| {"id": "FOO", "code": "FOO"} |         1 |           1 |
| {"id": "BAR", "code": "BAR"} |         1 |           1 |
+------------------------------+-----------+-------------+
2 rows in set, 1 warning (0.00 sec)

все еще получал то же предупреждение, хотя ...

Решение работает только для более чем одного параметра IN, оно прерывается, если вы попробуете его на первых двух запросах, которые изначально были успешными

mysql> select f.data, f.data_type, f.data_status 
from foo f 
where (JSON_EXTRACT(f.data, '$.code') in ('"BAR"'))    
and (f.data_type in (1))     
and (f.data_status in (1));
Empty set (0.00 sec)
...