Oracle SQL: попытка исключить строки на основе комбинации значений столбцов

У меня есть таблица со списком идентификаторов, из которых мне нужно исключить строки. Для каждой строки идентификатор может иметь одно значение в столбце comment_code. Мне нужно исключить из моих результатов идентификаторы, которые имеют комбинацию двух определенных значений, и сохранить идентификаторы, которые имеют только одно из этих двух значений. Извините, если это не ясно.

Пример таблицы:

ID     SEQUENCE     FUNCTION     COMMENT_CODE
---------------------------------------------------------------
1        1             tree          apple
1        2             bush          orange
2        1             tree          apple
2        2             tree          banana
3        1             bush          strawberry

Необходим вывод:

ID     SEQUENCE     FUNCTION     COMMENT_CODE
---------------------------------------------------------------
2        1             tree          apple

По сути, если в идентификаторе есть строка с «яблоком» в качестве кода комментария и строка с «оранжевым» в качестве кода комментария, я не хочу видеть этот идентификатор в своих результатах. Если идентификатор имеет строку с «яблоком» в качестве кода комментария, я хочу видеть их в своих результатах независимо от любого другого comment_code, который у них может быть, если у них нет оранжевого кода комментария.

Любая помощь будет принята с благодарностью. Я пытался использовать комбинацию предложений exists и not exists, а также listagg для группировки значений comment_code вместе для каждого идентификатора, но я не получаю ожидаемого результата.


person user1904581    schedule 11.02.2014    source источник


Ответы (3)


Этот подход использует агрегацию, чтобы найти все id, которые имеют оба значения. Это используется в качестве списка исключений с использованием left outer join:

select *
from table t left outer join
     (select id
      from table t
      group by t.id
      having sum(case when comment = 'apple' then 1 else 0 end) > 0 and
             sum(case when comment = 'orange' then 1 else 0 end) > 0
     ) toexclude
     on t.id = toexclude.id
where toexclude.id is null;
person Gordon Linoff    schedule 11.02.2014
comment
Спасибо Гордон! Я добавил AND T.COMMENT = 'apple', и теперь я получаю ожидаемые результаты. Я думал о том, чтобы сделать CASE вчера, но я просто не мог представить, как заставить его работать в этой ситуации. - person user1904581; 11.02.2014
comment
когда вы сказали group by t, вы имели в виду group by id? - person Caius Jard; 15.06.2017
comment
@КайусДжард. . . Спасибо. - person Gordon Linoff; 15.06.2017

Что-то вроде этого должно работать.

select *
from yourtable
where sequence = 1
and whatever
person Dan Bracuk    schedule 11.02.2014
comment
Дэн, я должен добавить, что в реальной таблице есть несколько разных кодов комментариев в произвольном порядке для каждого идентификатора, поэтому значение последовательности на самом деле не имеет значения. Код комментария «яблоко» может быть в последовательности 1 или может быть в последовательности 99, это просто зависит от порядка, в котором коды комментариев были добавлены к идентификатору. - person user1904581; 11.02.2014
comment
Тогда как узнать, какие комментарии вы хотите? - person Dan Bracuk; 11.02.2014
comment
Например, мне нужен комментарий «яблоко». Я смог получить то, что мне нужно, используя пример Гордона и добавив дополнительные критерии. - person user1904581; 11.02.2014

выберите *
из таблицы t
, где она существует (выберите 1 из двойной
, где t.function = 'tree' и t.comment_code = 'apple')

person Kiran    schedule 07.12.2017
comment
При ответе объясните, что вам нужно сделать, чтобы решить исходную проблему. Также используйте правильное форматирование для кодов. - person Mohammed Akhtar Zuberi; 07.12.2017