Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL SUM json стойности, групирани по json ключове

TL;DR: да, може да се направи, без да се знаят имената на ключовете предварително и нито един от алтернативните формати на данни няма предимство пред оригинала.

Това може да се направи, без да се знаят предварително имената на ключовете, но е болезнено... по принцип трябва да погледнете всяка стойност в таблицата, за да определите набора от различни ключове в таблицата, преди да можете да ги сумирате. Поради това изискване и факта, че всички алтернативни формати на данни могат да имат няколко ключа на запис, няма предимство да се използва нито един от тях.

Тъй като трябва да търсите всички различни ключове, е толкова лесно да направите сумите, докато ги търсите. Тази функция и процедура заедно ще направят това. Функцията, json_merge_sum , приема две JSON стойности и ги обединява, сумирайки стойностите, където ключът се появява и в двете стойности, напр.

SELECT json_sum_merge('{"key1": 1, "key2": 3}', '{"key3": 1, "key2": 2}')

Изход:

{"key1": 1, "key2": 5, "key3": 1}

Функционалният код:

DELIMITER //
DROP FUNCTION IF EXISTS json_merge_sum //
CREATE FUNCTION json_sum_merge(IN j1 JSON, IN total JSON) RETURNS JSON
BEGIN
  DECLARE knum INT DEFAULT 0;
  DECLARE jkeys JSON DEFAULT JSON_KEYS(j1);
  DECLARE kpath VARCHAR(20);
  DECLARE v INT;
  DECLARE l INT DEFAULT JSON_LENGTH(jkeys);
  kloop: LOOP
    IF knum >= l THEN
      LEAVE kloop;
    END IF;
    SET kpath = CONCAT('$.', JSON_EXTRACT(jkeys, CONCAT('$[', knum, ']')));
    SET v = JSON_EXTRACT(j1, kpath);
    IF JSON_CONTAINS_PATH(total, 'one', kpath) THEN
      SET total = JSON_REPLACE(total, kpath, JSON_EXTRACT(total, kpath) + v);
    ELSE
      SET total = JSON_SET(total, kpath, v);
    END IF;
    SET knum = knum + 1;
  END LOOP kloop;
  RETURN total;
END

Процедурата, count_keys , изпълнява еквивалента на GROUP BY клауза. Той намира всички различни стойности на col1 в таблицата и след това извиква json_sum_merge за всеки ред, който има тази стойност на col1 . Обърнете внимание, че заявката за избор на ред изпълнява SELECT ... INTO фиктивна променлива, така че не се генерира изход, и използва MIN() за да се гарантира, че има само един резултат (така че да може да бъде присвоен на променлива).

Процедурата:

DELIMITER //
DROP PROCEDURE IF EXISTS count_keys //
CREATE PROCEDURE count_keys()
BEGIN
  DECLARE finished INT DEFAULT 0;
  DECLARE col1val VARCHAR(20);
  DECLARE col1_cursor CURSOR FOR SELECT DISTINCT col1 FROM table2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished=1;
  OPEN col1_cursor;
  col1_loop: LOOP
    FETCH col1_cursor INTO col1val;
    IF finished=1 THEN
      LEAVE col1_loop;
    END IF;
    SET @total = '{}';
    SET @query = CONCAT("SELECT MIN(@total:=json_sum_merge(col2, @total)) INTO @json FROM table2 WHERE col1='", col1val, "'");
    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SELECT col1val AS col1, @total AS col2;
  END LOOP col1_loop;
END

За малко по-голям пример:

col1    col2    
aaa     {"key1": 1, "key2": 3}
bbb     {"key1": 4, "key2": 2}
aaa     {"key1": 50, "key3": 0}
ccc     {"key2": 5, "key3": 1, "key4": 3}
bbb     {"key1": 5, "key2": 1, "key5": 3}

CALL count_keys() произвежда:

col1    col2    
aaa     {"key1": 51, "key2": 3, "key3": 0}
bbb     {"key1": 9, "key2": 3, "key5": 3}
ccc     {"key2": 5, "key3": 1, "key4": 3}

Забележете, че извиках таблицата table2 в процедурата ще трябва да редактирате това (и в двете заявки), за да отговаря.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да проверите ефективността на mysql заявката?

  2. История на заявките в MySql Workbench (последната изпълнена заявка/заявки), т.е. създаване/промяна на таблица, избор, вмъкване на заявки за актуализиране

  3. Може ли някой да помогне да обясни защо неизползването на SQL JOIN е лоша практика и погрешно?

  4. Изберете редове, докато се покрие общото количество в колона (mysql)

  5. PHP добавя наклонени черти, sql инжекция все още е валидна?