ГДЕ x IN работает с одним значением, а не с несколькими на json - PullRequest
1 голос
/ 12 апреля 2019

Трудно понять проблему с запросом к полю json в MySQL. Столбец data имеет тип json.

Следующий запрос прекрасно работает

SELECT * FROM `someTable` WHERE data->'$.someData' in ('A')

Однако следующий ничего не возвращает.

 SELECT * FROM `someTable` WHERE data->'$.someData' in ('A','B')

Как ни странно, это тоже работает:

 SELECT * FROM `someTable` WHERE data->'$.someData'='A' OR data->'$.someData'='B'

Я понятия не имею, почему это происходит. Первоначально я думал, что WHERE x IN , выполняемый в формате запроса json, может выполнять что-то вроде &&, но даже если значения ('A', 'A'), он все равно не возвращает ничего, что по существу показывает, что больше, чем одно значение в ГДЕ x IN не будет работать.

ОБРАЗЕЦ ДАННЫХ (любой подойдет)

id | data (json)
1  | {"someData":"A"}
2  | {"someData":"B"}

Ответы [ 2 ]

5 голосов
/ 12 апреля 2019

Слишком долго для комментария ...

Похоже, это связано с оптимизацией, выполняемой MySQL, когда в выражении IN есть только одно значение (возможно, преобразовывающее его в выражение a = b), а затем игнорируется кавычки. Строго говоря,

SELECT * 
FROM `someTable` 
WHERE data->'$.someData' in ('A')

или

SELECT * 
FROM `someTable` 
WHERE data->'$.someData' = 'A'

не должен возвращать данные, потому что

SELECT data->'$.someData' 
FROM someTable;

возвращает

"A"
"B"

, что не совпадает с A. Вам нужно использовать JSON_UNQUOTE (или, если у вас MySQL 5.7.13 или более поздняя версия, оператор ->>), чтобы получить фактическое значение клавиши someData:

SELECT JSON_UNQUOTE(data->'$.someData') FROm someTable;
SELECT data->>'$.someData' FROm someTable;

что дает

A
B

, который затем отлично работает с выражением IN:

SELECT * 
FROM `someTable` 
WHERE JSON_UNQUOTE(data->'$.someData') in ('A','B')
-- or use WHERE data->>'$.someData' in ('A','B')

Выход:

id  data
1   {"someData":"A"}
2   {"someData":"B"}

Демонстрация на dbfiddle

0 голосов
/ 12 апреля 2019

Вы можете попробовать использовать объединение в подзапросе вместо предложения IN

SELECT * 
FROM `someTable` s 
INNER JOIN (
   select 'A'  col
   union 
   select 'B'
 )  t ON t.col = s.data->'$.someData 
...