我有父表让我们说P,Id,Name和Type。
P(
id (pk),
name,
type (type in (1..10) )
)
我有一个引用P的子表,让我们说这个表叫做B:
B (
id,
date,
other columns,
parent_id
)
现在问题是:表P
没有那么多记录,但表B
真的很大。如果Type = 3
,B
中的日期将始终与父记录相同。
所以我想从P
获取type = 3
的所有记录,并从表B
获取相应的日期。考虑到B非常大,最好的方法是什么?
我当时想写点什么
Select b.parent_id, p.name, max(b.date)
from B b
join P p on p.id = b.parent_id
group by b.parent_id, p.name
where p.type = 3
这里max(b.date)
或min(b.date)
无关紧要,因为Date是相同的。但表B
非常大。选择仅从P
并加入B
,例如“具有最小ID的子行”,或基本上任何子行,不是更好吗?
Select p.id, p.name, b.date
from P p
join B b on (p.id = b.parent_id and "take only first matching row")
where p.type = 3
尝试一下:
Select p.id, p.name, (select b.date from B where p.id = b.parent_id and rownum = 1) date
from P p
where p.type = 3
根据要求,假设您有b (parent_id)
的索引。如果您拥有的数据是:
create table p (
id number(6) primary key not null,
name varchar2(20),
type number(2)
);
insert into p (id, name, type) values (10, 'John', 2);
insert into p (id, name, type) values (11, 'Peter', 3);
insert into p (id, name, type) values (12, 'Albert', 3);
insert into p (id, name, type) values (13, 'Mary', 4);
insert into p (id, name, type) values (14, 'Diego', 3);
create table b (
id number(6),
date1 date,
parent_id number(6),
constraint fk1_b foreign key (parent_id) references p (id)
);
create index ix1_b on b (parent_id);
insert into b (id, date1, parent_id) values (101, timestamp '2018-01-01 12:34:56', 10);
insert into b (id, date1, parent_id) values (102, timestamp '2018-01-02 12:34:57', 11);
insert into b (id, date1, parent_id) values (103, timestamp '2018-01-03 12:34:58', 11);
insert into b (id, date1, parent_id) values (104, timestamp '2018-01-04 12:34:59', 11);
insert into b (id, date1, parent_id) values (105, timestamp '2018-01-04 12:55:10', 12);
insert into b (id, date1, parent_id) values (106, timestamp '2018-01-04 12:55:11', 12);
insert into b (id, date1, parent_id) values (107, timestamp '2018-01-04 12:55:12', 12);
查询将是:
select p.*, bl.date1
from p,
lateral (
select * from b where b.parent_id = p.id fetch next 1 rows only
) bl
where p.type = 3;
结果:
ID NAME TYPE DATE1
-- ------ ---- ---------------------
11 Peter 3 2018-01-02 12:34:57.0
12 Albert 3 2018-01-04 12:55:10.0
现在,如果在p
中没有任何行的b
中存在行(在我的示例中为“Diego”),则需要外连接:
select p.*, bl.date1
from p
outer apply (
select * from b where b.parent_id = p.id fetch next 1 rows only
) bl
where p.type = 3;
结果:
ID NAME TYPE DATE1
-- ------ ---- ---------------------
11 Peter 3 2018-01-02 12:34:57.0
12 Albert 3 2018-01-04 12:55:10.0
14 Diego 3 <null>
干杯!