Логика запросов для получения ожидаемых результатов на основе списка исключений группы - PullRequest
0 голосов
/ 16 ноября 2018

Ниже приведен тривиальный пример с ожидаемыми результатами для справки.

БД: 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 голосов
/ 16 ноября 2018
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 (+)
;
...