Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MySQL SUM nilai json dikelompokkan berdasarkan kunci json

TL;DR: ya, ini dapat dilakukan tanpa mengetahui nama kunci sebelumnya, dan tidak ada format data alternatif yang memiliki keunggulan dibandingkan aslinya.

Hal ini dapat dilakukan tanpa mengetahui nama kunci terlebih dahulu tetapi ini menyakitkan... pada dasarnya Anda harus melihat setiap nilai dalam tabel untuk menentukan kumpulan kunci yang berbeda dalam tabel sebelum Anda dapat menjumlahkannya. Karena persyaratan ini, dan fakta bahwa format data alternatif semuanya dapat memiliki beberapa kunci per entri, tidak ada keuntungan untuk menggunakan salah satu dari mereka.

Karena Anda harus mencari semua kunci yang berbeda, melakukan penjumlahan dengan mudah saat Anda mencarinya. Fungsi dan prosedur ini bersama-sama akan melakukan itu. Fungsinya, json_merge_sum , mengambil dua nilai JSON dan menggabungkannya, menjumlahkan nilai di mana kunci muncul di kedua nilai, mis.

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

Keluaran:

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

Kode fungsi:

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

Prosedurnya, count_keys , melakukan yang setara dengan GROUP BY ayat. Ia menemukan semua nilai yang berbeda dari col1 di tabel dan kemudian memanggil json_sum_merge untuk setiap baris yang memiliki nilai col1 . Perhatikan bahwa kueri pemilihan baris melakukan SELECT ... INTO variabel dummy sehingga tidak ada output yang dihasilkan, dan menggunakan MIN() untuk memastikan hanya ada satu hasil (sehingga dapat ditetapkan ke variabel).

Prosedurnya:

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

Untuk contoh yang sedikit lebih besar:

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() menghasilkan:

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

Catatan Saya telah memanggil tabel table2 dalam prosedur, Anda perlu mengeditnya (di kedua kueri) agar sesuai.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ubah waktu tanggal JS ke waktu tanggal MySQL

  2. Adakah cara untuk memilih dari tabel MySQL di mana bidang diakhiri dengan karakter/angka tertentu?

  3. Apakah saya memerlukan koneksi php mysql di setiap fungsi yang menggunakan database?

  4. Apa yang dimaksud dengan pooling=false dalam string koneksi MySQL?

  5. Kodekan API Pertama Anda Dengan Node.js dan Express:Hubungkan Database