выбрать только совпадающие записи из двух таблиц - PullRequest
0 голосов
/ 19 августа 2011

Я использую Oracle 10g Вот мой сценарий:

У меня есть две таблицы

class1(groupName, subgroup)
class2(groupName, subgroup, ind)

Вот мои данные выглядят так:

class1
groupName  subgroup
     A      1
     A      2
     B      3
     C      4
     C      4
     C      5
     D      6


class2
groupName  subgroup IND
     A      1        Y     
     A      1        N
     A      2        Y
     A      2        N
     B      3        Y
     C      4        Y
     C      4        N

Теперь,Мне нужно получить данные, которые имеют совпадающие groupName и subGroup как в class1, так и в class2 (не обязательно различное совпадение).В дополнение к этому столбец IND должен иметь пару значений 'Y' и 'N' для каждой подгруппы в классе 2. Например, в приведенном выше примере GroupName A квалифицируется, поскольку A существует как в class1, так и в class2 и имеет подгруппу 1 и2 существуют как в class1, так и в class2, а столбец IND в таблице class2 содержит пару «Y» и «N» для каждой подгруппы (т. Е. 1 и 2).

Остальные записи не квалифицированы, потому что: Группа B имеет подгруппу 3, которая существует как в class1, так и в class2, но у нее нет пар «Y» и «N» для подгруппы 3 в class2.Группы C и D не квалифицированы, потому что вся ее подгруппа (4,5) не существует в классе 2.

У меня более 700 000 записей как в таблице class1, так и в class2.Любой человек знает, как эффективно получить эту информацию.

Ответы [ 3 ]

2 голосов
/ 19 августа 2011

Создает ли это то, что вам нужно?

SELECT *
FROM class1 c1
JOIN class2 c2 ON c1.groupName = c2.groupName
        AND c1.subgroup = c2.subgroup
WHERE
    (
    SELECT COUNT(DISTINCT ind)
    FROM class2 c2a
    WHERE c2a.groupName = c1.groupName
        AND c2a.subgroup = c2a.subgroup
    ) = 2
  AND
    (
    SELECT COUNT(DISTINCT subgroup)
    FROM class1 c1b
    WHERE c1b.groupName = c1.groupName
    ) =
    (
    SELECT COUNT(DISTINCT subgroup)
    FROM class2 c2b
    WHERE c2b.groupName = c2.groupName
    )
0 голосов
/ 19 августа 2011

Нечто подобное должно помочь ...

select 
  groupName
from (

  select -- Get number of good subgroups for each group
    groupName                      as groupName,
    subGroupCount                  as subGroupCount,
    sum( decode(ynCount, 2,1, 0) ) as goodGroupCount
  from (

      select -- Find which subgroups are good (contains both Y and N)
        c1set.groupName        as groupName,
        c1set.subGroup         as subGroup,
        c1set.subGroupCount    as subGroupCount,
        count(distinct c2.IND) as ynCount
      from
        (
          select -- Collect group/subgroup sets and get number of subGroups
            distinct 
              c1.groupName                        as groupName,
              c1.subGroup                         as subGroup,
              count(distinct c1.subGroup)
                over (parttition by c1.groupName) as subGroupCount
          from
            class1 c1
        )
               c1set,
        class2 c2
      where
        c2.groupName (+) = c1set.groupName
        and
        c2.subGroup (+) = c1set.subGroup
      group by
        c1set.groupName,
        c1set.subGroup,
        c1set.subGroupCount

    )
  group by
    groupName, subGroupCount

)
where
  subGroupCount = goodGroupCount

Извините, сейчас я не могу самостоятельно протестировать этот код. Пожалуйста, прокомментируйте, если вы обнаружили несоответствие.

0 голосов
/ 19 августа 2011

Если не имеет значения, что столбец IND имеет Y и N конкретно, вы можете сделать это:

select t1.groupName from
( select count(class1.groupName) a, groupName from class1 group By groupName) t1
 inner join 
( select count(class2.groupName) a, groupName from class2 group by groupName) t2
on t1.groupName = t2.groupName and 2*t1.a = t2.a

Если это имеет значение, вы можете изменить второй внутренний запрос следующим образом:

select count(class2.groupName) a, groupName from class2 group by groupName
  having  max(ind) = 'Y' and min(ind) = 'N'

Изменить для поддержки дополнительных тестов, упомянутых в комментариях:

select distinct t1.groupName from
( select count(class1.groupName) a, groupName, subgroup from class1 
  group By groupName, subgroup) t1
 inner join 
( select count(class2.groupName) a, groupName, subgroup from class2 
  group by groupName, subgroup
  having  max(ind) = 'Y' and min(ind) = 'N') t2
on t1.groupName = t2.groupName and t1.subgroup = t2.subgroup and 2*t1.a = t2.a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...