2017-12-27 173 views
1

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

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

PlanPlanSet表

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

ExcludedPlans表

Plan1 
Plan2 

这里Planset1包含计划1和Plan4,并Planset2只包含计划2。因此Planset1不应排除,Planset2应排除在外。

喜欢的东西,

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

请问您可以添加表的模式吗? – cdaiga

+0

Planset2包含plan5,为什么它应该被视为与Planset1不同? – Mat

+0

@ Mat-抱歉我编辑了这些值。现在PlanSet2仅包含plan2 – user1940878

回答

2

你想PLANSETS中的每一个计划都在排除计划列表中。

关于这个关系的思考,你需要将这两张表连在一起,并发现每一面的计划数量是相同的。这意味着我们必须允许它们有不同的意思,表示左外连接。

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并计划唯一的,并且EXCLUDEDPLANS是计划唯一的。如果这个假设是不正确,那么你就需要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 
+0

我希望PLANSETS的所有东西都在计划集中的每个计划都在排除计划列表中。我应该只找到这样的计划集,其中所有计划都存在于ExcludedPlans表中 – user1940878

+0

所以,我们只需要将'<>'改为'='然后(我已经完成了)。您的示例查询只需要planset。您是否真的想要所有内容? – Ben

+0

@ ben-我只想要planset。我试着用=改变<>,它的工作正常!! Thanksss !!顺便说一下,是否有可能将这个查询转换为Eclipse链接查询? – user1940878

2

据说这是为了找到只有这样plansets其中的所有计划都存在于ExcludedPlans表。如果需要此类计划集的所有行,则省略第一行中的独特行,并添加所需的任何列。

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 
) 

如果相反只有这样plansets这并不是所有的计划都出现在ExcludedPlans表应该被选中,然后更改子查询的WHERE条件selected.all <> selected.present

+0

嗨,你的外部内联视图有两个WHERE子句,这是阻止执行。我修改了这个。我也将'count(*)'列表达式的名字从'all'改为'ct'。这是因为'all'是一个保留字,不能用作名称。我希望你不介意。您可以使用[dbfiddle](http://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=deb753011f14a0b2bec8a5c5ec13679a)之类的内容查看您的代码在发布之前是否工作(或之后!)您的代码[现在返回正确的结果] (http://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=be06852d3dbf406897c0e82a49521a17)。 – Ben

+0

@Ben我根本不介意!谢谢你的小提琴链接,我会检查一下 - 在过去我使用了sqlfiddle,它的表现不好,现在我只是盲目地回应:(你的解决方案很好,因为它更简洁,也可以用count()代替解码零点是整齐的,并没有发生在我身上 – Demo

0

该查询返回PlanPlanSet这些都是记录套仅排除计划:

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

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

LiveSQL demo.