Найти группу записей, соответствующих определенным критериям

У меня есть следующие данные:

ID --- ParentID --- DataValue  
1  ---    1     ---    A  
2  ---    1     ---    B  
3  ---    1     ---    C  
4  ---    4     ---    B  
5  ---    4     ---    C  
6  ---    6     ---    A  
7  ---    6     ---    B  
8  ---    6     ---    C  
9  ---    6     ---    D

Для каждой группы записей (сгруппированных по ParentID) я хотел бы найти все группы, у которых нет записи, содержащей "A", в качестве значения данных

Поскольку группы 1 и 6 содержат хотя бы одну запись, в которой в качестве значения данных указано "A", я бы не хотел их видеть. Я хотел бы видеть только записи 4 и 5 (которые являются частью группы 4), поскольку в этой группе нет записей, имеющих "А".

Любая помощь очень ценится!

5 ответов

Решение
SELECT
  ID,
  ParentID,
  DataValue
FROM
  MyTable
WHERE
  NOT EXISTS (
    SELECT 1 
      FROM MyTable i
     WHERE i.ParentId = MyTable.ParentId AND i.DataValue = 'A'
  )

Индекс над (ParentId, DataValue) Рекомендуется, если стол большой.

Это должно сделать

SELECT
  *
FROM
  yourtable
WHERE
  parentID NOT IN (SELECT DISTINCT parentID FROM yourtable WHERE DataValue = 'A')

Однопроходное решение:

select ParentID
from YourTable
group by ParentID
having sum(case DataValue when 'A' then 1 else 0 end) = 0

Это работает? Вы не говорите, находятся ли все данные в одной таблице или нет.

select parentid from yourtable
where groupid IN ( select DISTINCT groupid from yourtable where datavalue = 'A' )
group by parentid

Мне нравится ответ Томалака, но я почему-то скептически отношусь к тому, что он выполнится NOT EXISTS для каждой строки в таблице, а не для каждого отдельного ParentId, поэтому, когда группы большие, он будет медленнее, чем необходимо.

В этом случае ответ Габи был бы лучше в сочетании с индексом DataValue и индексом ParentId.

Просто для удовольствия, как насчет:

SELECT R.Id, R.ParentId, R.DataValue FROM (
    SELECT DISTINCT ParentId FROM YourTable
    EXCEPT SELECT DISTINCT ParentId FROM YourTable WHERE DataValue = 'A'
) L
LEFT JOIN YourTable R ON R.ParentId = L.ParentId

(Также с одним индексом на DataValue и одним индексом на ParentId)

Другие вопросы по тегам