从两个表

从两个表

问题描述:

我使用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 

现在,我需要获取在class1和class2中都具有匹配的groupName和subGroup的数据(不一定非常匹配)。除此之外,IND列应该为类2中的每个子组具有'Y'和'N'值。例如,在上面的示例中,GroupName A是合格的,因为A存在于class1和class2中,并且它具有子组1和2存在于class1和class2中,而class2表中的IND列对于每个子组(即1和2)具有一对'Y'和'N'。

其余的记录是不合格的,因为:B组的子组3的存在于class1和class2中,但它在class2的子组3中没有'Y'和'N'对。 C组和D组没有资格,因为它的所有子组(4,5)都不存在于class2中。

我在表class1和class2上有超过700,000条记录。任何人都知道什么是获得这些信息的有效方法。

+0

class1是否至少与class2的子组数量一样多?换句话说,你可以有E,7级,1级,E,7,Y; E,7,N,E,8,Y ..在2级? – Mikeb

+0

不,这并非总是如此。有一段时间,小组可能存在于class1中,但不存在于class2中,反之亦然。 – niceApp

+0

假设在您的示例(A,2,N)中删除。 “A”组在这种情况下是否合格?换句话说,组*的所有子组都必须是合格的,否则就足够了。 – ThinkJet

这是否创造世界卫生大会你需要吗?

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

这也适用于我的测试数据集,只要Y和N是IND中唯一的字符,但我认为它比我的更容易阅读 – Mikeb

+0

我认为它也行不通。因为你加入了groupName和subgroup,所以它将选择组c和子组4,因为它存在于两个类中。但不应该选择,因为子组5不存在于第2类。 – niceApp

+0

这不起作用。即使在class1中至少有一个子组值与在class2中存在一个子组值并且存在其他子组值不匹配的情况下,它也会返回数据;这不应该是这样。 (不同的)所有子组都应该在class1和class2中匹配。 – niceApp

如果不要紧的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 
+0

谢谢你Mikeb。但我不明白2 * t1.a在上面的代码中。 IND列确实很重要。而且你只加入了groupName,但是这将如何确保class1中的相同子组也存在于class2中。如果在class1中存在任何子组并且不存在于class2中,那么它不是合格的,反之亦然。我没有看到这个条件应用于上面的代码。 – niceApp

+0

如果IND列具有正确数量的条目,那么class1中的行分组计数是class2中相同计数的一半大小 - 因此在2 * t1.a = t2.a上加入。你对分组是正确的。如果你有正确数量的不匹配标签,这将失败。但它确实适用于您的测试数据! – Mikeb

类似的东西必须帮助...

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 

抱歉,我现在不能由我自己测试此代码。如果您发现任何不一致,请发表评论。