はセットアップです:
create table t (id serial primary key, content json);
insert into t set content = '{"tags": ["tag_1", "tag_2"]}';
insert into t set content = '{"tags": ["tag_3", "tag_2"]}';
insert into t set content = '{"tags": ["tag_1", "tag_2"]}';
あなたが任意のタグ・アレイ内のタグの最大数がわかっている場合は、UNIONを使用して、すべてのタグを抽出することができます。
select id, json_extract(content, '$.tags[0]') AS tag from t
union
select id, json_extract(content, '$.tags[1]') from t;
+----+---------+
| id | tag |
+----+---------+
| 1 | "tag_1" |
| 2 | "tag_3" |
| 3 | "tag_1" |
| 1 | "tag_2" |
| 2 | "tag_2" |
| 3 | "tag_2" |
+----+---------+
あなたが最も長い配列内のタグの数だけUNION句サブクエリを必要としています。
次にあなたが派生テーブルでこれを入れて、その上で集約を行うことができます
select tag, count(*) as count
from (
select id, json_extract(content, '$.tags[0]') as tag from t
union
select id, json_extract(content, '$.tags[1]') from t
) as t2
group by tag
order by count desc;
+---------+-------+
| tag | count |
+---------+-------+
| "tag_2" | 3 |
| "tag_1" | 2 |
| "tag_3" | 1 |
+---------+-------+
2番目のテーブルではなく、JSON配列にタグを保存した場合これが容易になるだろう:
create table tags (id bigint unsigned, tag varchar(20) not null, primary key (id, tag));
insert into tags set id = 1, tag = 'tag_1';
insert into tags set id = 1, tag = 'tag_2';
insert into tags set id = 2, tag = 'tag_3';
insert into tags set id = 2, tag = 'tag_2';
insert into tags set id = 3, tag = 'tag_1';
insert into tags set id = 3, tag = 'tag_2';
select tag, count(*) as count
from tags
group by tag
order by count desc;
+-------+-------+
| tag | count |
+-------+-------+
| tag_2 | 3 |
| tag_1 | 2 |
| tag_3 | 1 |
+-------+-------+
このソリューションは、IDごとにいくつのタグがあっても機能します。 IDごとにタグのリストの最大長を知る必要はありません。
JSONは、半構造化データの 'ドキュメント'を保存する必要がある場合に便利ですが、ドキュメントを既約データ値として扱う場合にのみ便利です。ドキュメントの要素にアクセスして関係演算を適用するとすぐに、ドキュメント指向のアプローチはその弱点を示します。
ありがとうございました!非常に役立ちます。 1週間この作業をする! – user43857