mysql. Как вернуть сообщения в нужном формате?

код таблицы img_message:

CREATE TABLE `img_message` (
    `id_message` int NOT NULL,
    `name_img` char(255) NOT NULL,
    `path_img` char(255) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

код таблицы message:

CREATE TABLE `message` (
    `id` int NOT NULL,
    `thread_id` int NOT NULL,
    `id_user` int NOT NULL,
    `text_message` char(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
    `prev_message` int DEFAULT NULL,
    `next_message` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

код процедуры mysql:

CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `sp_get_all_message_thread` (IN `value` INT)  NO SQL
BEGIN
    SELECT json_arrayagg(
        JSON_OBJECT( 'id', message.id, 
                     'text', message.text_message, 
                     'prev_message', message.prev_message, 
                     'next_message', message.next_message, 
                     'img', img_message.path_img
                   )
        ) as json_message 
    from message 
    LEFT JOIN img_message ON id = img_message.id_message
    WHERE message.thread_id = value
    GROUP BY img_message.id_message;
END

ответ процедуры:

[{"id": 1, "img": null, "text": "ура, субкота!", "next_message": null,
"prev_message": null}] 

[{"id": 2, "img": "./img/шлепа.png", "text":
"Милые коты!", "next_message": 3, "prev_message": null}, 

{"id": 2,
"img": "./img/kot.png", "text": "Милые коты!", "next_message": 3,
"prev_message": null}] 

[{"id": 3, "img": "./img/miliu-cot.png",
"text": "милые коты везде!", "next_message": null, "prev_message": 2}]

ответ который требуется мне:

    [
{"id": 1, "img": null, "text": "ура, субкота!", "next_message": null, "prev_message": null},

{"id": 2, "img": ["./img/шлепа.png", "./img/kot.png"], "text": "Милые коты!", "next_message": 3, "prev_message": null},

{"id": 3, "img": ["./img/miliu-cot.png"], "text": "милые коты везде!", "next_message": null, "prev_message": 2}]

inser into таблицы img_message:

    INSERT INTO `img_message` (`id_message`, `name_img`, `path_img`) VALUES
(3, 'miliu-cot.png', './img/miliu-cot.png'),
(2, 'шлепа.png', './img/шлепа.png'),
(2, 'kot.png', './img/kot.png');

insert into таблицы message:

INSERT INTO `message` (`id`, `thread_id`, `id_user`, `text_message`, `prev_message`, `next_message`) VALUES
(1, 2, 2, 'ура, субкота!', NULL, NULL),
(2, 2, 1, 'Милые коты!', NULL, 3),
(3, 2, 2, 'милые коты везде!', 2, NULL);

мой второй вариант решения этой задачи (считаю его ужасным):

BEGIN
SELECT
json_object('id', t1.id, 'text', t1.text_message, 'prev_message', t1.prev_message, 'next_message', t1.next_message, 'img', CONCAT(' [',GROUP_CONCAT("'",t2.path_img,"'"),']')
) as message_and_img
FROM message AS t1
LEFT JOIN img_message AS t2 ON t1.id = t2.id_message
WHERE t1.thread_id = value
GROUP BY t1.id;
END

как это можно реализовать, уже бьюсь над этой проблемой довольно долго, но так и не получилось её решить.


Ответы (1 шт):

Автор решения: Akina
SELECT JSON_ARRAYAGG(obj) output
FROM (
    SELECT JSON_OBJECT( 
        'id', message.id, 
        'text', message.text_message, 
        'prev_message', message.prev_message, 
        'next_message', message.next_message, 
        'img', JSON_ARRAYAGG(img_message.path_img) 
        ) obj
    FROM message 
    LEFT JOIN img_message ON message.id = img_message.id_message
    GROUP BY message.id, 
             message.text_message, 
             message.prev_message, 
             message.next_message
    ) subquery

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=c1e945801a06391ba9e6ac455111b6da

→ Ссылка