查询逻辑以基于组排除列表获得预期结果

时间:2018-11-16 11:35:40

标签: sql oracle oracle12c

请在下面的简单示例中找到预期结果,以供参考。

数据库:Oracle Database 12c

示例查询:

with x as
(select 'John' farmer, 'FRUITGROUPA,FRUITGROUPB,ALLFRUIT,VEGGROUPA,VEGGROUPB,VEGGROUPC' grouper from dual),
y as
(select x.farmer,regexp_substr (x.grouper, '[^,]+', 1, level)  grouper
from x
connect by level <= regexp_count(x.grouper,',')+1),
z as
(select 'FRUITGROUPA' grouper,'FRUITS' classer, 'APPLE' exclusion from dual union all
 select 'FRUITGROUPB' grouper,'FRUITS' classer, 'APPLE,BANANA,WATERMELON' exclusion from dual union all
 select 'ALLFRUIT' grouper,'FRUITS' classer, '' exclusion from dual union all
 select 'VEGGROUPA' grouper,'VEG' classer, 'POTATO' exclusion from dual union all
 select 'VEGGROUPB' grouper,'VEG' classer, 'CARROT,LADYFINGER,POTATO' exclusion from dual union all
 select 'VEGGROUPC' grouper,'VEG' classer, 'POTATO,CARROT' exclusion from dual )
select * from y,z where y.grouper = z.grouper

如果运行查询,则会得到相应的数据:

+--------+-------------+-------------+---------+--------------------------+
| FARMER |   GROUPER   |  GROUPER_1  | CLASSER |        EXCLUSION         |
+--------+-------------+-------------+---------+--------------------------+
| John   | FRUITGROUPA | FRUITGROUPA | FRUITS  | APPLE                    |
| John   | FRUITGROUPB | FRUITGROUPB | FRUITS  | APPLE,BANANA,WATERMELON  |
| John   | ALLFRUIT    | ALLFRUIT    | FRUITS  |                          |
| John   | VEGGROUPA   | VEGGROUPA   | VEG     | POTATO                   |
| John   | VEGGROUPB   | VEGGROUPB   | VEG     | CARROT,LADYFINGER,POTATO |
| John   | VEGGROUPC   | VEGGROUPC   | VEG     | POTATO,CARROT            |
+--------+-------------+-------------+---------+--------------------------+

最终查询的预期输出:

+---------+-----------+
| CLASSER | EXCLUSION |
+---------+-----------+
| FRUITS  |           |
| VEG     | POTATO    |
+---------+-----------+

逻辑:

在头等舱(水果)中,FRUITGROUPA和FRUITGROUPB中的农民被排除在耕作苹果之外,而ALLFRUIT组中则没有。因此,当涉及到总体限制时,允许农民与所有其他水果一起种植苹果,

在第二类(蔬菜)中,与类别(蔬菜)相对应的所有群体的农民都被排除在种植马铃薯之外。因此,从总体上讲,它不属于种植马铃薯,但允许种植所有其他蔬菜。

在整个情况下,我都无法找到给出此类输出的查询。

谢谢。

1 个答案:

答案 0 :(得分:0)

with groupsOneLine as(
  select 'John' farmer, 
         'FRUITGROUPA,FRUITGROUPB,ALLFRUIT,VEGGROUPA,VEGGROUPB,VEGGROUPC' grouper 
    from dual
),
groups_ as (
  select x.farmer,
         regexp_substr (x.grouper, '[^,]+', 1, level)  grouper
    from groupsOneLine x
 connect by level <= regexp_count(x.grouper,',')+1
),
exclusionsOneLine as (
 select 'FRUITGROUPA' grouper,'FRUITS' classer, 'APPLE' exclusion from dual union all
 select 'FRUITGROUPB' grouper,'FRUITS' classer, 'APPLE,BANANA,WATERMELON' exclusion from dual union all
 select 'ALLFRUIT' grouper,'FRUITS' classer, '' exclusion from dual union all
 select 'VEGGROUPA' grouper,'VEG' classer, 'POTATO' exclusion from dual union all
 select 'VEGGROUPB' grouper,'VEG' classer, 'CARROT,LADYFINGER,POTATO' exclusion from dual union all
 select 'VEGGROUPC' grouper,'VEG' classer, 'POTATO,CARROT' exclusion from dual 
),
exclusions_ as (
  select distinct 
         x.grouper,
         x.classer,
         regexp_substr (x.exclusion, '[^,]+', 1, level)  exclusion
    from exclusionsOneLine x
 connect by level <= regexp_count(x.exclusion,',')+1
),
exclusionsPerClasser as (
  select count(1) count_,
         x.classer,
         x.exclusion
    from exclusions_ x
   group by x.classer,
            x.exclusion
),
groupsPerClasser as (
  select count(1) count_,
         x.classer
    from exclusionsOneLine x
   group by x.classer
),
excludeInAllGroups  as (
  select e.classer,
         e.exclusion
    from groupsPerClasser g,
         exclusionsPerClasser e
   where g.classer = e.classer
     and g.count_ = e.count_
)
select g.classer,
       e.exclusion
  from groupsPerClasser g,
       excludeInAllGroups e
 where g.classer = e.classer (+)
;