两个 table 之间的关系,中间有一个可选的第三个 table
Relation between two tables with an optional third table in between
我有以下架构和数据。
--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_c
到 link 的直接 link 的话,它基本上是 table_a
和 table_c
之间的关系,有一条通过 table_b
的路线table_a
.
table_c
中的每个元素将填充 a_id
或 b_id
。如果我们有 a_id
,我们就没有 b_id
。如果我们有 b_id
,我们就没有 a_id
。两者不能同时为 null
,也不能同时为非空。
现在我被要求创建一个物化视图来显示 table_a
和 table_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_a
、table_b
、table_c
分别有 300 万、600 万和 100 万条记录。过滤所有内容的实际结果存在于具有大约 10k 条记录的物化视图中。
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)
;
我有以下架构和数据。
--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_c
到 link 的直接 link 的话,它基本上是 table_a
和 table_c
之间的关系,有一条通过 table_b
的路线table_a
.
table_c
中的每个元素将填充 a_id
或 b_id
。如果我们有 a_id
,我们就没有 b_id
。如果我们有 b_id
,我们就没有 a_id
。两者不能同时为 null
,也不能同时为非空。
现在我被要求创建一个物化视图来显示 table_a
和 table_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_a
、table_b
、table_c
分别有 300 万、600 万和 100 万条记录。过滤所有内容的实际结果存在于具有大约 10k 条记录的物化视图中。
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)
;