Как использовать JSON_ARRAYAGG в JSON_OBJECT без экранирования контента - PullRequest
1 голос
/ 26 марта 2020

. Здравствуйте,

У меня есть запрос SQL, который возвращает массив JSON. Я хочу упростить его, используя нативные JSON функции mysql / mariadb.

Проблема в том, что он ускользает от подмассива. Я думаю, что подзапрос анализируется как строка символов, но Я не нашел способа и не знаю, можно ли заставить mariadb понять, что это массив.

SELECT JSON_ARRAYAGG(
    JSON_OBJECT(
        'uuid', UuidFromBin(staff.uuid),
        'username', staff.username,
        'name', staff.name,
        'surname', staff.surname,
        'skills', (
            SELECT JSON_ARRAYAGG(
                JSON_OBJECT(
                    'uuid', UuidFromBin(s.uuid),
                    'name', s.name,
                    'shortName', s.short_name,
                    'description', s.description
                )
            )
            FROM staff_skills
            JOIN skills s ON s.id = skill_id
            WHERE staff_skills.staff_id = events_staff.staff_id
        )
    )
)
FROM events_staff
JOIN staff ON staff.id = staff_id
LEFT JOIN skills s ON s.id = events_staff.skill_id
WHERE event_id = 3

дают

[
    {
        "uuid": "78edbe24-6e30-11ea-b47e-0242ac120003",
        "username": "xxx",
        "name": "xxx",
        "surname": "xxx",
        "skills": "[{\"uuid\": \"78efb999-6e30-11ea-b47e-0242ac120003\", \"name\": \"skillName\", \"shortName\": \"skillShortName\", \"description\": null},{\"uuid\": \"78efca7e-6e30-11ea-b47e-0242ac120003\", \"name\": \"Permis B\", \"shortName\": \"Perm. B\", \"description\": null}]"
    }
]

Мой старый запрос работает нормально, но не читается:

SELECT CONCAT(
    '[',
        GROUP_CONCAT(
            CONCAT(
                '{',
                    '"uuid":"', UuidFromBin(staff.uuid),
                    '", "username":"', staff.username,
                    '", "name":"', staff.name,
                    '", "surname":"', staff.surname,
                    '", "skills":[',
                        IFNULL(
                            (
                                SELECT GROUP_CONCAT(
                                    CONCAT(
                                        '{"uuid":"', UuidFromBin(s.uuid), '", "name":"', s.name, '", "shortName":"', s.short_name, '"',
                                                    IFNULL(
                                            CONCAT(
                                                ', "description":"', s.description, '"'
                                            ),
                                            ''
                                        ),
                                        '}'
                                    ) SEPARATOR ', '
                                ) FROM staff_skills JOIN skills s ON s.id = skill_id WHERE staff_skills.staff_id = events_staff.staff_id
                            ),
                            ''
                        ),
                    ']',
                '}'
            ) SEPARATOR ', '
        ),
    ']'
)                
FROM events_staff
JOIN staff ON staff.id = staff_id
LEFT JOIN skills s ON s.id = events_staff.skill_id
WHERE event_id = 3

, которые дают

[
   {
      "uuid":"78edbe24-6e30-11ea-b47e-0242ac120003",
      "username":"vlortet",
      "name":"vlortet",
      "surname":"Lortet",
      "skills":[
         {
            "uuid":"78efb999-6e30-11ea-b47e-0242ac120003",
            "name":"Premiers Secours en Équipe de Niveau 2",
            "shortName":"PSE2"
         },
         {
            "uuid":"78efca7e-6e30-11ea-b47e-0242ac120003",
            "name":"Permis B",
            "shortName":"Perm. B"
         }
      ]
   }
]

Спасибо за чтение:)


РЕДАКТИРОВАТЬ: В конце концов я нахожу "плохой" способ. Я использую JSON_EXTRACT для преобразования строки в JSON ... Итак, у нас есть несколько преобразований. JSON> STRING> JSON ...

SELECT JSON_ARRAYAGG(
    JSON_OBJECT(
        'uuid', UuidFromBin(staff.uuid),
        'username', staff.username,
        'name', staff.name,
        'surname', staff.surname,
        'skills', JSON_EXTRACT(
            (SELECT JSON_ARRAYAGG(
                JSON_OBJECT(
                    'uuid', UuidFromBin(s.uuid),
                    'name', s.name,
                    'shortName', s.short_name,
                    'description', s.description
                )
            )
            FROM staff_skills
            JOIN skills s ON s.id = skill_id
            WHERE staff_skills.staff_id = events_staff.staff_id),
            '$'
        )
    )
)
FROM events_staff
JOIN staff ON staff.id = staff_id
LEFT JOIN skills s ON s.id = events_staff.skill_id
WHERE event_id = 3
...