Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Christophe.

Asked: November 09, 2018 - 10:45 am UTC

Last updated: November 09, 2018 - 3:43 pm UTC

Version: 11.2.0.1.0

Viewed 1000+ times

You Asked

I have 4 tables

table item_values
  (item_key, item_value)

table filter_model
  (filter_key)
  
table item_includes
  (include_key, filter_key_fk, item_key, include_value)

table item_excludes
  (exclude_key, filter_key_fk, item_key, exclude_value)

I'd like to get all items from item_values for each filter_model that matches the includes and are not in the excludes

Query should be like

select item_values.item_key,
       item_values.item_value,
       filter_model.filter_key,
       item_includes.include_value
  from item_includes,
       filter_model,
       item_values
  where filter_model.filter_key=item_includes.filter_key_fk
    and item_values.item_value=item_includes.include_value
    and not exists (select 'x'
                      from item_excludes
                      where item_excludes.filter_key_fk=filter_model.filter_key
                        and item_excludes.include_value=item_values.item_value);


this works fine but I need to create materialized views for fast refresh for performance purpose.
So the subquery forbids the fast_refresh.

select item_values.item_key,
       item_values.item_value,
       filter_model.filter_key,
       item_excludes.exclude_value
  from item_excludes,
       filter_model,
       item_values;


My idea was to vreate a MV for the exclusions (getting all excluded items) elligible for a fast refresh :

create materialized view mv_excluded
as
select item_values.item_key,
       item_values.item_value,
       filter_model.filter_key,
       item_excludes.exclude_value
  from item_excludes,
       filter_model,
       item_values
  where filter_model.filter_key=item_excludes.filter_key_fk
    and item_values.item_value=item_excludes.exclude_value;



and then create the main MV with the inclusions and removing rows in the mv_excluded.
How can I do this ?


and Chris said...

There is a trick!

You can write not exists queries as an outer join, returning those rows where a (mandatory) column from the outer-joined table is null.

You can fast refresh these:

create table t1 (
  c1 int primary key
);
create table t2 (
  c1 int primary key
);

insert into t1 values ( 1 );
insert into t1 values ( 2 );

insert into t2 values ( 1 );
commit;

create materialized view log on t1 with rowid including new values;
create materialized view log on t2 with rowid including new values;

create materialized view mv
refresh fast on commit
as 
  select t1.rowid t1rid, t2.rowid t2rid, t1.* 
  from   t1, t2
  where  t1.c1 = t2.c1 (+)
  and    t2.c1 is null;

select c1 from mv;  

C1   
   2 

insert into t2 values ( 2 );
commit;

select c1 from mv;  

no rows selected

insert into t1 values ( 3 );
commit;

select c1 from mv;  

C1   
   3 

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Christophe Marchadier, November 09, 2018 - 3:32 pm UTC

Works fine, thanks !

In my model I have to create intermediate MV to fit your example but I succeeded
Chris Saxon
November 09, 2018 - 3:43 pm UTC

Great

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.