两个表之间的关系,中间有可选的第三个表

时间:2016-11-17 10:01:18

标签: sql oracle materialized-views

我有以下架构和数据。

--drop table table_c;
--drop table table_b;
--drop table table_a;

create table table_a (
  id    number(3,0)  primary key,
  value varchar2(10)
);

create table table_b (
  id    number(3,0)  primary key,
  a_id  number(3,0)  not null,
  value varchar2(10),
  constraint b_fk1 foreign key (a_id) references table_a(id)
);

create table table_c (
  id    number(3,0)  primary key,
  a_id  number(3,0)  null,
  b_id  number(3,0)  null,
  value varchar2(10),
  constraint c_fk1 foreign key (a_id) references table_a(id),
  constraint c_fk2 foreign key (b_id) references table_b(id)
);

-- table a
insert into table_a (id, value) values (1, 'a');
insert into table_a (id, value) values (2, 'b');
-- table b
insert into table_b (id, a_id, value) values (1, 1, 'aa');
insert into table_b (id, a_id, value) values (2, 2, 'bb');
-- table c with ref to a
insert into table_c (id, a_id, value) values (1, 1, 'aaa');
insert into table_c (id, a_id, value) values (2, 2, 'bbb');
-- table c with ref to b
insert into table_c (id, b_id, value) values (3, 1, 'ccc');
insert into table_c (id, b_id, value) values (4, 2, 'ddd');
COMMIT;

如果我们没有从table_atable_c的直接链接,那么table_btable_c之间的关系基本上是table_a的路线table_c

a_id中的每个元素都会填充b_ida_id。如果我们有b_id,我们就没有b_id。如果我们有a_id,我们就没有null。两者不能同时为table_a,或同时为非空。

现在我要求创建一个显示table_ctable_c之间关系的实体化视图。

我的第一个想法是更新a_id,以便--drop materialized view mv_d; --drop materialized view log on table_c; --drop materialized view log on table_b; --drop materialized view log on table_a; create materialized view log on table_a with rowid, sequence; create materialized view log on table_b with rowid, sequence; create materialized view log on table_c with rowid, sequence; create materialized view mv_d refresh fast on commit enable query rewrite as select a.value as a_val, c.value as c_val, a.rowid as a_rowid, b.rowid as b_rowid, c.rowid as c_rowid from table_a a, table_b b, table_c c where (c.a_id is null and c.b_id = b.id and b.a_id = a.id) or (c.a_id is not null and c.a_id = a.id); execute dbms_stats.gather_table_stats( user, 'mv_d' ) ; 始终保持最新状态。客户对数据库有很强的把握,并禁止我这样做!

select * from mv_d;

-- note, the rowids are for information only, but are abbreviated to only show how they're different.
 a_val | c_val | a_rowid | b_rowid | c_rowid
-------+-------+---------+---------+---------
 a     | aaa   | GAAA    | WAAA    | mAAA
 a     | ccc   | GAAA    | WAAA    | mAAC
 a     | aaa   | GAAA    | WAAB    | mAAA
 b     | bbb   | GAAB    | WAAA    | mAAB
 b     | bbb   | GAAB    | WAAB    | mAAB
 b     | ddd   | GAAB    | WAAB    | mAAD

我对这个MV的问题是结果不是我所期望的。这就是我得到的。请注意,rowid缩写为显示它们的差异和实际结果,这意味着它们为重复的原因。

select * from mv_d

理想情况下,我会从rowid获得以下结果(条形 a_val | c_val -------+------- a | aaa a | ccc b | bbb b | ddd 列,ofc)。

table_a

如何在物化视图中获得该结果?

请注意,我的实际数据库分别为table_btable_cIF EXISTS (SELECT Up.id,descr,isServiceManual FROM tbl_odw_asyncmessage Async JOIN tbl_ODW_AsyncMessageParam AsyncP ON asyncMessageId=Async.id JOIN tbl_ODW_UnloadingPoint Up ON up.id=AsyncP.value WHERE type=3) Begin Update tbl_ODW_UnloadingPoint set isServiceManual=1 where isServiceManual=0 and exists ( SELECT Up.id FROM tbl_odw_asyncmessage Async JOIN tbl_ODW_AsyncMessageParam AsyncP ON asyncMessageId=Async.id where tbl_ODW_UnloadingPoint.id = AsyncP.value and type=3 ) End ELSE PRINT N'No values' 提供了300万,600万和100万条记录。过滤了所有内容的实际结果存在于具有大约10k记录的物化视图中。

1 个答案:

答案 0 :(得分:4)

select      a.value as a_val
           ,c.value     as c_val
           ,a.rowid     as a_rowid
           ,b.rowid     as b_rowid
           ,c.rowid     as c_rowid

from                    table_a a

            join        (           table_c c

                        left join   table_b b

                        on          c.b_id  = b.id
                        )

            on           a.id = nvl (b.a_id,c.a_id) 

;

对于物化视图,请使用此旧样式代码

select      a.value as a_val
           ,c.value     as c_val
           ,a.rowid     as a_rowid
           ,b.rowid     as b_rowid
           ,c.rowid     as c_rowid

from        dmarkovitz.table_a a
           ,dmarkovitz.table_b b
           ,dmarkovitz.table_c c

where       c.b_id  = b.id (+)
        and a.id    = nvl (b.a_id,c.a_id) 
;