Единственный способ решить эту проблему в версиях MySQL до 8 - использовать хранимую функцию, чтобы найти минимальное значение time
из каждого набора тегов.Примерно так:
DELIMITER //
CREATE FUNCTION min_time(tags JSON)
RETURNS INT
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE mint INT DEFAULT 9999;
DECLARE thist INT;
SET thist = JSON_EXTRACT(tags, CONCAT('$[', i, '].time'));
WHILE thist IS NOT NULL DO
IF thist < mint THEN
SET mint = thist;
END IF;
SET i = i + 1;
SET thist = JSON_EXTRACT(tags, CONCAT('$[', i, '].time'));
END WHILE;
RETURN mint;
END //
Тогда вы можете использовать такой запрос:
SELECT id, title, tags, min_time(tags) AS min_time
FROM posts
WHERE JSON_CONTAINS(tags , '{"tag": "android"}')
ORDER BY min_time
Вывод:
id title tags tags->'$[*].time' min_time
4 Fourth Post [{"tag": "mobiles", "time": 472}, {"tag": "android", "time": 121}] [472, 121] 121
5 Fifth Post [{"tag": "android", "time": 122}, {"tag": "apple", "time": 140}] [122, 140] 122
3 Third Post [{"tag": "android", "time": 124}] [124] 124
8 Eigth Post [{"tag": "android", "time": 126}] [126] 126
Демонстрация на dbfiddle
Это может быть слишком сложно, так как сортируется по минимальному времени любого тега в сообщении.Если вы только хотите отсортировать по времени, связанному с тегом android
(который вы ищете), вы можете использовать этот упрощенный запрос:
SELECT id, title, tags,
JSON_EXTRACT(tags, CONCAT(SUBSTRING_INDEX(JSON_UNQUOTE(JSON_SEARCH(tags, 'one', 'android')), '.', 1), '.time')) AS tag_time
FROM posts
WHERE JSON_CONTAINS(tags , '{"tag": "android"}')
ORDER BY tag_time
Вывод:
id title tags tag_time
3 Third Post [{"tag": "android", "time": 75}] 75
4 Fourth Post [{"tag": "mobiles", "time": 472}, {"tag": "android", "time": 121}] 121
5 Fifth Post [{"tag": "android", "time": 122}, {"tag": "apple", "time": 140}] 122
8 Eigth Post [{"tag": "android", "time": 126}] 126
Демонстрация на dbfiddle