2017-12-27 80 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.