通过连接避免联合?
我的问题出在 Oracle 上,但可能与数据库无关(?)。
我有以下表格:
aa
vid cb
--- --
1 10
2 15
bb
vid cb
--- --
3 25
4 24
**rep*
repid vid p
----- --- --
99 1 aa
99 2 aa
99 3 bb
99 4 bb
列 p 指示在哪个表中获取行。 实际上,aa 和 bb 有很大不同,p 与表名不匹配,但给出了到达那里的方法。这个例子只是我遇到问题的一个简化。 请注意,实际情况中,有超过 2 个表 aa 和 bb(有 6 个)。 我想要一个返回此的查询:
repid vid p cb
----- --- -- --
99 1 aa 10
99 2 aa 15
99 3 bb 25
99 4 bb 24
以下工作: (a)
select rep.vid, rep.p, cb
from (
select 'aa' as p,vid,cb from aa
union all
select 'bb' as p, vid,cb from bb) u,rep
where rep.p=u.p and rep.vid=u.vid
(b)
select rep.vid, rep.p,
decode(rep.p, 'aa', (select cb from aa where vid=rep.vid),
'bb', (select cb from bb where vid=rep.vid)) cb
from rep
但我想在视图中使用查询,在该视图上可以进行谓词推送。
所以问题 1 是:以下是否允许谓词推送。 问题 2:(即使问题 1 是肯定的)有没有一种方法可以在不使用联合但使用连接的情况下做到这一点。 问题 3:或者只是简单地说,更好的方法?
创建数据的脚本:
create table bb (vid number(1), cb number(2));
create table aa (vid number(1), cb number(2));
create table rep(rid number(2), vid number(1), p varchar2(2));
insert into rep (rid,vid,p) values (99, 4,'bb');
insert into rep (rid,vid,p) values (99, 3,'bb');
insert into rep (rid,vid,p) values (99, 2,'aa');
insert into rep (rid,vid,p) values (99, 1,'aa');
insert into bb (vid,cb) values (4,24);
insert into bb (vid,cb) values (3,25);
insert into aa (vid,cb) values (2,15);
insert into aa (vid,cb) values (1,10);
commit;
My problem is on Oracle, but is probably database independent (?).
I have the following tables:
aa
vid cb
--- --
1 10
2 15
bb
vid cb
--- --
3 25
4 24
**rep*
repid vid p
----- --- --
99 1 aa
99 2 aa
99 3 bb
99 4 bb
The column p indicates in which table to get the row.
In reality, aa and bb are much more different, and p does not match to the table name, but gives a way to get there. The example is just a simplication where I have a problem.
Note than in reality, there are more than 2 tables aa and bb (there are 6).
I want a query that returns this:
repid vid p cb
----- --- -- --
99 1 aa 10
99 2 aa 15
99 3 bb 25
99 4 bb 24
The following works:
(a)
select rep.vid, rep.p, cb
from (
select 'aa' as p,vid,cb from aa
union all
select 'bb' as p, vid,cb from bb) u,rep
where rep.p=u.p and rep.vid=u.vid
(b)
select rep.vid, rep.p,
decode(rep.p, 'aa', (select cb from aa where vid=rep.vid),
'bb', (select cb from bb where vid=rep.vid)) cb
from rep
But I would like to use the query in a view, on which there can be predicate pushing.
So question 1 is: would the following allow predicate pushing.
Question 2: (even if yes for question 1) is there a way to do this without union, but with joins.
Question 3: Or just simply, a better way?
Script to create the data:
create table bb (vid number(1), cb number(2));
create table aa (vid number(1), cb number(2));
create table rep(rid number(2), vid number(1), p varchar2(2));
insert into rep (rid,vid,p) values (99, 4,'bb');
insert into rep (rid,vid,p) values (99, 3,'bb');
insert into rep (rid,vid,p) values (99, 2,'aa');
insert into rep (rid,vid,p) values (99, 1,'aa');
insert into bb (vid,cb) values (4,24);
insert into bb (vid,cb) values (3,25);
insert into aa (vid,cb) values (2,15);
insert into aa (vid,cb) values (1,10);
commit;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不再有 Oracle 实例可供使用,但确实尝试过使用 PostgreSQL,这可能会引起兴趣?
我对 PostgreSQL 的实验表明,实际上联合效果更好。我根据您的联合查询创建了一个视图,postgres 能够将诸如“cb BETWEEN 12 AND 27”之类的谓词推送到 aa 和 bb 的扫描中。
相比之下,我创建了一个使用连接的视图:
现在的问题是,coalesce() 阻止了涉及 cb 的谓词被推入 aa 和 bb 的扫描中。
I don't have an Oracle instance to hand any more, but did try things with PostgreSQL, which might be of interest anyway?
My experiment with PostgreSQL suggests that actually the union works better. I created a view based on your union query, and postgres was able to push a predicate such as "cb BETWEEN 12 AND 27" into the scans of aa and bb.
By constrast, I created a view that uses joins:
The problem now is that the coalesce() blocks a predicate involving cb being pushed into the scans of aa and bb.
join
可以指定多个条件。表名可以是一个。例如,如果table1
有一个名为TableName
的列引用其他表,您可以使用:您可以通过这种方式添加任意数量的表。
至于你的第三个问题,总有更好的方法。问题是,这样就够了吗?如果没有,您能否定义可接受的解决方案的要求?
A
join
can specify multiple conditions. The table name can be one. For example, iftable1
has a column calledTableName
that references other tables, you could use:You can add an arbitrary number of tables this way.
As to your third question, there is always a better way. The question is, does this way suffice? If not, can you define the requirements for an acceptable solution?