Подсчет слов в JSON массиве mySQL - PullRequest
2 голосов
/ 08 мая 2020

Мне нужно подсчитать истинные и ложные слова в типе данных JSON. У меня это JSON в ячейке:

{"1": true, "2": false, "3": true}

Количество значений может отличаться. Я понимаю, что могу подсчитать общее количество значений в массиве, но как я могу отдельно подсчитать истинное и ложное? Для общего подсчета я использовал JSON_LENGTH()

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Один из вариантов - использовать подход, описанный ниже, содержащий функции JSON_LENGTH(), JSON_EXTRACT() и JSON_SEARCH() вместе, даже для версии 5.7 (5.7.13+), где массив (js) извлечен в подзапросе, и они разделены на отдельные массивы для каждого значения (true и false) с использованием функции JSON_SEARCH(), содержащей all в качестве второго аргумента, а затем подсчитываются функцией JSON_LENGTH():

SELECT ID, 
       JSON_LENGTH( JSON_SEARCH(js, 'all', 'true') ) AS Cnt_True,
       JSON_LENGTH( JSON_SEARCH(js, 'all', 'false') ) AS Cnt_False
  FROM ( SELECT *, JSON_EXTRACT(jsdata, '$.*') AS js
           FROM tab ) t

при условии, что поле JSON имеет значения в кавычках, такие как "true" и "false"

JSON_EXTRACT(jsdata, '$.*'), все еще можно использовать в случае, если логические значения не заключены в кавычки, как в вашем случае. Но на этот раз потребуются некоторые строковые операции. Здесь я предпочел использовать функцию CHAR_LENGTH():

SELECT ID,  
       CHAR_LENGTH(js) - CHAR_LENGTH(REPLACE(js, 'true', SPACE(LENGTH('true')-1))) 
        AS Cnt_True,
       CHAR_LENGTH(js) - CHAR_LENGTH(REPLACE(js, 'false', SPACE(LENGTH('false')-1))) 
        AS Cnt_False        
  FROM
  ( SELECT *, JSON_EXTRACT(jsdata, '$.*') AS js
      FROM tab ) t

Демо

0 голосов
/ 09 мая 2020

Вот один из вариантов с использованием json_table(), доступный в MySQL 8.0.

Сначала вы можете превратить каждый объект json в массив значений, используя путь $.*'. Затем вы можете передать полученный массив json в json_table(), что поместит каждое значение в отдельную строку. Последним шагом является условное агрегирование.

Предполагая, что столбец json называется js, это будет:

select sum(x.val = 'true') cnt_true, sum(x.val = 'false') cnt_false
from mytable t
cross join json_table(js -> '$.*', '$[*]' columns (val varchar(5) path '$')) x

Демо на DB Fiddle

Пример данных (я добавил еще одну строку, чтобы сделать это более понятным):

| js                                 |
| :--------------------------------- |
| {"1": true, "2": false, "3": true} |
| {"bar": false, "foo": true}        |

Результаты:

cnt_true | cnt_false
-------: | --------:
       3 |         2
...