Вы правы, это будет становиться все медленнее и медленнее по мере добавления новых тегов, которые вы хотите искать в дополнительных предложениях UNION. Каждое предложение UNION - это дополнительный запрос, который необходимо запланировать и выполнить. Кроме того, вы не сможете сортировать, когда закончите.
Вы ищете базовую технику хранения данных. Сначала позвольте мне воссоздать вашу схему с одной дополнительной таблицей.
create table a (document_id int, tag varchar(10));
insert into a values (1, 'tag1'), (1, 'tag2'), (1, 'tag3'), (2, 'tag2'),
(3, 'tag1'), (3, 'tag2'), (4, 'tag1'), (5, 'tag3');
create table b (tag_group_id int, tag varchar(10));
insert into b values (1, 'tag1'), (1, 'tag2'), (2, 'tag3');
Таблица b содержит «группы тегов». Группа 1 включает в себя tag1 и tag2, а группа 2 содержит tag3.
Теперь вы можете изменить таблицу b, чтобы представить интересующий вас запрос. Когда вы будете готовы сделать запрос, вы создадите временные таблицы для хранения сводных данных:
create temporary table c
(tag_group_id int, count_tags_in_group int, tags_in_group varchar(255));
insert into c
select
tag_group_id,
count(tag),
group_concat(tag)
from b
group by tag_group_id;
create temporary table d (document_id int, tag_group_id int, document_tag_count int);
insert into d
select
a.document_id,
b.tag_group_id,
count(a.tag) as document_tag_count
from a
inner join b on a.tag = b.tag
group by a.document_id, b.tag_group_id;
Теперь c содержит количество тегов для группы тегов, а d содержит количество тегов, которые каждый документ имеет для каждой группы тегов. Если строка в c совпадает со строкой в d, то это означает, что документ содержит все теги в этой группе тегов.
select
d.document_id as "Document ID",
c.tags_in_group as "Matched Tag Group"
from d
inner join c on d.tag_group_id = c.tag_group_id
and d.document_tag_count = c.count_tags_in_group
Отличительной особенностью этого подхода является то, что вы можете запускать отчеты типа «Сколько документов имеют 50% или более тегов в каждой из этих групп тегов?»
select
d.document_id as "Document ID",
c.tags_in_group as "Matched Tag Group"
from d
inner join c on d.tag_group_id = c.tag_group_id
and d.document_tag_count >= 0.5 * c.count_tags_in_group