2016-11-17 70 views
4

之間我有以下模式和數據。兩張表格之間的關係可選第三個表格在

--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_b路線table_atable_c之間的關係,如果我們沒有直接的聯繫,從table_ctable_a

table_c中的每個元素都將填充a_idb_id。如果我們有a_id,我們沒有b_id。如果我們有b_id,我們沒有a_id。兩者不能同時爲null,或者同時爲非空。

現在我被要求創建一個物化視圖,顯示table_atable_c之間的關係。

我的第一個想法是更新table_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') ; 

我對這個MV的問題是,結果不是我所期望的。這是我得到的。請注意rowid縮寫以顯示它們的差異和實際結果,這意味着它們爲什麼是重複的。

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 

理想情況下,我會得到從select * from mv_d以下結果(扎rowid列,OFC)。

a_val | c_val 
-------+------- 
a  | aaa 
a  | ccc 
b  | bbb 
b  | ddd 

如何在物化視圖中獲得該結果?

請注意,我的實際數據庫分別爲table_atable_b,table_c的300萬,600萬和100萬條記錄。過濾所有內容的實際結果存在於具有大約10k條記錄的物化視圖中。

+0

'選擇不同a_val,從mv_d' c_val? – jarlh

+0

@jarlh擁有1億條記錄的中間mv_d?不,我不能那樣。問題出在物化視圖的查詢中,而不是查詢之後。 –

回答

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) 
; 
+0

我會測試,但我的DBA堅持認爲,該聯接不工作在物化視圖... –

+0

@OlivierGrégoire,請檢查編輯答案 –

+0

現在,它就像一個魅力!非常非常感謝你! –

相關問題