Mysql [JSON] -> / ->> Есть у кого объяснение феномена?

AnrDaemon

Продвинутый новичок
Код:
DROP TABLE IF EXISTS `testtable`; 
CREATE TABLE `testtable` (`field` TEXT);
INSERT INTO `testtable` VALUES
('{"order":1}'),
('{"order":11}'),
('{"order":2}');
SELECT MAX(field->'$.order'), MAX(field->>'$.order') FROM testtable;

+-----------------------+------------------------+
| MAX(field->'$.order') | MAX(field->>'$.order') |
+-----------------------+------------------------+
| 11                    | 2                      |
+-----------------------+------------------------+
 

fixxxer

К.О.
Партнер клуба
Попробую угадать: в первом случае число, во втором кастится к строкам.

В postgresql, во всяком случае, именно так.
 

AnrDaemon

Продвинутый новичок
Непонятно, почему раскавычивание приводит к кастингу в строку?
 

fixxxer

К.О.
Партнер клуба
JSON_UNQUOTE(json_val)

Unquotes JSON value and returns the result as a utf8mb4 string
 

fixxxer

К.О.
Партнер клуба
-> просто извлекает часть json-а, которая тоже json, без каких-либо преобразований. ->> конвертирует из json в text. Все остальное можно решить кастингом. По крайней мере, в postgresql этого мне вполне хватает для всех мыслимых задач. В mysql вроде очень похоже сделано (судя по документации, сам не пользовался).
 

AnrDaemon

Продвинутый новичок
-> просто извлекает часть json-а, которая тоже json, без каких-либо преобразований.
Ладно, хорошо. Такая логика мне понятна.
->> конвертирует из json в text.
Вот только непонятно, зачем кастовать в текст.
Для большего единообразия?… Я бы понял, если бы -> всегда текст возвращала, "ибо JSON", тогда это ещё имело бы какой-то смысл.
 

fixxxer

К.О.
Партнер клуба
Ну потому что получить нормальную строку, а не JSON-представление строки - это достаточно часто нужный кейс.

Поведения, похожего на пхпшный json_decode, в sql получить нельзя, потому что у столбца четко определен тип, а в json может быть любая помойка. Если нужен int - надо явно кастить к нему.

-> - это function(json $value): json
->> - это function(json $value): string
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Да, я понял. Просто непонятно, почему -> возвращает типизированный результат. Это слегка сносит крышу.
 

fixxxer

К.О.
Партнер клуба
Он возвращает всегда один тип - json. ;)

А вот как определен MAX для типа json - это отдельный вопрос, в этом вся "магия" в мыскле. Postgresql, например, тебя пошлет с этим нафиг:

ERROR: function max(jsonb) does not exist
Хотя если сделать не MAX, а ORDER BY, то та же магия вылезет и в постгресе (ну а тут деваться некуда, order by то всегда должен быть определен хоть как-то).

Вообще, думаю, сортировку по json вполне разумно считать undefined behavior.
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Ясно. Будем, считать, что крышу сносит мускулю. Так как-то спокойнее.

И, да, в оригинале было ORDER BY, MAX() тут только для наглядности.
Пришлось сделать ORDER BY CAST(... AS SIGNED).
 
Последнее редактирование:
Сверху