I am currently working on a internal legacy project and to get more familiar with the backend logic and database design, I have decided to rewrite all queries from the old fashion SQL-86 standard into a more modern one. But I am stuck on one big view and one participial join (this example is very simplified):
select t4.id
from
t1,
t2,
t3,
t4
where
t2.t1id = t1.id(+)
and t2.tmpid = t3.tmpid(+)
and t4.id = t3.t4id(+)
group by t4.id
having
count (t2.t1id) = count(t3.tmpid);
which is based on the following (example) table structure:
create table t1 (
id number generated by default on null as identity primary key,
title varchar(100)
);
create table t2 (
t1id number not null,
tmpid number not null
);
create table t3 (
tmpid number not null,
t4id number not null
);
create table t4 (
id number generated by default on null as identity primary key,
title varchar(100)
);
insert into t1(id, title) values(1, 'Order1');
insert into t1(id, title) values(2, 'Order2');
insert into t4(id, title) values(1, 'Attribute 1');
insert into t4(id, title) values(2, 'Attribute 2');
insert into t2(t1id, tmpid) values(1, 1);
insert into t2(t1id, tmpid) values(1, 2);
insert into t2(t1id, tmpid) values(2, 1);
insert into t2(t1id, tmpid) values(2, 2);
insert into t3(tmpid, t4id) values(1, 1);
insert into t3(tmpid, t4id) values(2, 2);
insert into t3(tmpid, t4id) values(2, 1);
The query in question results in the following result when removing the "group by" and "having" statement:
select *
from
t1,
t2,
t3,
t4
where
t2.t1id = t1.id(+)
and t2.tmpid = t3.tmpid(+)
and t4.id = t3.t4id(+)
order by t1.id
First of all I thought the and t4.id = t3.t4id(+)
was just a "wrong" (well it works for over a decade now so it can't really be wrong) specified old fashioned join and just replaced it with a and t3.t4id = t4.id(+)
so it would be a "left join" on ANSI SQL, but then the rows with a "null" values just disappears and the having count(t2.t1id) = count(t3.tmpid)
results to true on every row.
So my question is to what resolves the and t4.id = t3.t4id(+)
in a ANSI SQL and why? Out of desperation I have tried it with every join and I can't reproduce the null values which are mandatory for the "having".
Or is there is there another way to implement this query in a modern way?