如何在oracle中实现'Only in'条件?

How to achieve 'Only in' condition in oracle?

如何在oracle中实现'Only in'条件?

我有两个 table 'PlanPlanSet' 和 'ExcludedPlans'。 PlanPlanSet 包含计划和与每个计划关联的计划集。我想从 PlanPlanSet 中获取所有记录,其中 Plan ONLY IN ExcludedPlans.

计划计划集table

Plan1 - Planset1
Plan2 - Planset2
Plan3 - Planset3
Plan4 - Planset1
Plan5 - Planset5

排除的计划Table

Plan1
Plan2

这里Planset1包含Plan1和Plan4,Planset2只包含Plan2。因此不应排除 Planset1,而应排除 Planset2。

有点像,

select pps.planset 
from PlanPlanSet pps 
 where pps.planNumber only in (select ex.planNumber 
                               from ExcludedPlan ex);

这应该只找到所有计划都存在于 ExcludedPlans table 中的行星集。如果需要此类行星集的所有行,请省略第一行的不同并添加所需的任何列。

Select distinct planset
From PlanPlanSet ps1
Where
exists
(
  Select selected.planset
  From
  (
    Select ps2.planset, count(*) ct, sum(decode(ep2.plan, null, 0, 1)) present
    From PlanPlanSet ps2
    Left join ExcludedPlans ep2 on ep2.plan = ps2.plan
    Group by ps2.planset
  ) selected
  Where selected.ct = selected.present and ps1.planset = selected.planset
)

相反,如果仅应选择并非所有计划都存在于 ExcludedPlans table 中的行星集,则将子查询 WHERE 条件更改为 selected.all <> selected.present

您想要 PLANSETS 中的所有内容,其中该行星集中的每个计划都在排除计划列表中。

从关系上考虑这个问题,您需要将两个表连接在一起,并发现每一侧的计划数在哪里相同。这意味着我们必须允许它们不同,这意味着 LEFT OUTER JOIN。

select p.planset
  from plansets p
  left outer join excludedplans e
    on p.plan = e.plan
 group by p.planset
having count(p.plan) = count(e.plan)

假设 PLANSETS 在 PLANSET 和 PLAN 上是唯一的,并且 EXCLUDEDPLANS 在 PLAN 上是唯一的。如果这个假设不正确,那么您需要 count(distinct ...

如果您想要 PLANSETS 中的所有数据,则可以将逻辑放入分析函数中

select *
  from ( select p.*
              , count(p.plan) over (partition by p.planset) as planset_ct
              , count(e.plan) over (partition by p.planset) as excluded_ct
           from plansets p
           left outer join excludedplans e
             on p.plan = e.plan
                )
 where planset_ct = excluded_ct

此查询 returns PlanPlanSet 中的所有记录,这些记录仅为排除计划集:

select * from PlanPlanSet pss
where not exists
  ( select planname from planPlanSet x
    where x.setname = pss.setname
    minus
    select planname from ExcludedPlans)
/

MINUS 运算符从顶部子查询中生成一组记录,这些记录不存在于底部子查询中。当结果为空集时,计划集仅包含排除的计划。 MINUS 不是一个非常快速的操作,所以如果您要处理大量记录,这可能不是最好的方法。但是,它确实具有检索 PlanPlanSet 列的优势,而不仅仅是 setname.

LiveSQL demo.