Если вы обнаружите, что решение с GROUP BY и HAVING может привести к путанице, просто сначала объедините цвета в строке, используя LISTAGG.
Обратите внимание, что при использовании INNER JOIN
исключаются фигуры без цветов (здесь 4- см. пример данных ниже).
Также предикат WHERE
ограничивает только соответствующие цвета.
select s.shape_id,
LISTAGG(c.color, ',') WITHIN GROUP (ORDER BY c.color) color_lst
from shape s
join shape_color c
on s.shape_id = c.shape_id
where c.color in ('red', 'pink', 'blue', 'yellow')
group by s.shape_id
;
SHAPE_ID COLOR_LST
---------- ---------------------------
1 blue,pink,red,yellow
2 red
3 blue,pink,yellow
Ваша задача настолько же проста, как и исключить единственный отрицательный случай из всех четырех цветов:
with colors as (
select s.shape_id,
LISTAGG(c.color, ',') WITHIN GROUP (ORDER BY c.color) color_lst
from shape s
join shape_color c
on s.shape_id = c.shape_id
where c.color in ('red', 'pink', 'blue', 'yellow')
group by s.shape_id
)
select shape_id
from colors
where color_lst != 'blue,pink,red,yellow'
SHAPE_ID
----------
2
3
Вы должны позаботиться о том, чтобы убедиться, что цвета внутри фигуры уникальны.Если нет, вы должны добавить подзапрос, который различает цвета в форме. То же самое относится и к решениям HAVING
.
Пример данных
create table shape as
select 1 shape_id from dual union all
select 2 shape_id from dual union all
select 3 shape_id from dual union all
select 4 shape_id from dual;
create table shape_color as
select 1 shape_id, 'red' color from dual union all
select 1 shape_id, 'pink' color from dual union all
select 1 shape_id, 'blue' color from dual union all
select 1 shape_id, 'yellow' color from dual union all
select 2 shape_id, 'red' color from dual union all
select 3 shape_id, 'pink' color from dual union all
select 3 shape_id, 'blue' color from dual union all
select 3 shape_id, 'yellow' color from dual;