Как получить значение из последнего элемента внутри документа MySQL JSON? - PullRequest
1 голос
/ 05 августа 2020

Я использую Mysql версию 8.0.18-commercial

Мой MySQL запрос возвращает JSON Document для одного из значений столбца.

ServerName      Status
abc.com         JSON Document(as shown below)

Столбец Status аналогично приведенному ниже:

{
  "STEP1": {
    "state": "STARTED",
    "startTime": "2020-08-05T04:40:45.021Z"
  },
  ....
  ....
  "STEP4": {
    "state": "ENDED",
    "startTime": "2020-08-05T05:08:36.286Z"
  }
}

Желаемый результат:

ServerName      Status
abc.com         ENDED

Я хочу найти последний STEP в моем JSON Document, а затем получить значение state для это.

Я написал следующий запрос, но он не отображает последнее state значение:

SELECT ServerName,
  (SELECT j.state
   FROM table t1
   CROSS JOIN json_table(Status, '$[*]' columns (state varchar(1000) PATH '$.state', startTime varchar(100) PATH '$.startTime')) j
   WHERE t1.id = t.id
   ORDER BY row_number() OVER (
                               ORDER BY j.startTime) DESC
   LIMIT 1) AS Status
FROM table AS t 

1 Ответ

1 голос
/ 05 августа 2020

json_table() не делает то, что вы думаете здесь: он предназначен для работы с массивом JSON , в то время как ваш столбец содержит JSON объект .

Альтернативный подход - использовать json_table() с json_keys() для извлечения ключей объекта в виде строк: затем вы можете извлечь соответствующие значения, ранжировать строки, имеющие одинаковые servername, и оставить только верхнюю строку для каждой группы :

select servername, state, starttime
from (
    select 
        t.servername,
        json_unquote(json_extract(t.status, concat('$.', j.k, '.startTime'))) starttime,
        json_unquote(json_extract(t.status, concat('$.', j.k, '.state'))) state,
        row_number() over(
            partition by t.servername 
            order by json_unquote(json_extract(t.status, concat('$.', j.k, '.startTime'))) desc
        ) rn
    from mytable t
    cross join json_table(
        json_keys(t.status), 
        '$[*]' columns (k varchar(50) path '$')
    ) j
) t
where rn = 1

Демонстрация на DB Fiddle :

servername | state | starttime               
:--------- | :---- | :-----------------------
abc.com    | ENDED | 2020-08-05T05:08:36.286Z
...