TL; DR: はい、事前にキー名を知らなくても実行できます。また、代替データ形式のいずれも元の形式に勝る利点はありません。
これは、キー名を事前に知らなくても実行できますが、面倒です...基本的に、テーブル内のすべての値を調べて、合計する前にテーブル内の個別のキーのセットを判別する必要があります。この要件と、代替データ形式はすべてエントリごとに複数のキーを持つことができるという事実のために、それらのいずれかを使用する利点はありません。
すべての個別のキーを探す必要があるため、それらを探しているときに合計を行うのは簡単です。この関数とプロシージャは一緒にそれを行います。関数json_merge_sum
、2つの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()
を使用します 結果が1つだけであることを確認します(変数に割り当てることができるようにします)。
手順:
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
と呼んでいることに注意してください 手順では、それに合わせて(両方のクエリで)編集する必要があります。