I have the following query:
select * from
from assignments dah, employees emp
where
dah.person_id=emp.person_id(+)
and
(dah.effective_end_date between emp.date_from(+) and emp.date_to(+)
and dah.effective_end_date between emp.valid_from(+) and emp.valid_to(+))
or
(dah.effective_start_date between emp.date_from(+) and emp.date_to(+)
and dah.effective_start_date between emp.valid_from(+) and emp.valid_to(+))
I get the following message: 'outer join operator (+) not allowed in operand of OR or IN'. I know about using 2 unions with inner joins is a solution, but I can't use it because I actually have a lot of code (code I provided is just an example).
Edit: i need this done via oracle syntax, because i work with data warehousing and our ETL doesn't fully support explicit syntax. Maybe there is something i am not seeing and this can be written differently?
Edit nr.2 : Maybe date overlapping logic can somehow be implemented without using OR and with oracle syntax?
Introduction. Although an ON clause is required for each operation in an outer join in a FROM clause, an outer join can itself also include a WHERE clause. Any restriction in the WHERE clause is applied only to the table that is the final result of the outer join.
You apply the outer join operator (+) in parentheses following a column name within predicates that refer to columns from two tables, as shown in the following examples: The following query performs a left outer join of tables T1 and T2. Include both tables in the FROM clause, separated by a comma.
The SQL OUTER JOIN returns all rows from both the participating tables which satisfy the join condition along with rows which do not satisfy the join condition. The SQL OUTER JOIN operator (+) is used only on one side of the join condition only.
To use the WHERE clause to perform the same join as you perform using the INNER JOIN syntax, enter both the join condition and the additional selection condition in the WHERE clause. The tables to be joined are listed in the FROM clause, separated by commas. This query returns the same output as the previous example.
Use explicit left join
syntax:
select *
from employees emp left join
assignments dah
on dah.person_id = emp.person_id and
((dah.effective_end_date between emp.date_from and emp.date_to and
dah.effective_end_date between emp.valid_from and emp.valid_to
) or
(dah.effective_start_date between emp.date_from and emp.date_to and
dah.effective_start_date between emp.valid_from and emp.valid_to
)
);
A simple rule is never to use a comma in the from
clause. Always use explicit join
syntax.
Note: Technically, your outer join syntax would have the tables in the other order:
from assignments dah left join
employees emp
on . . .
I swapped them on purpose. The left join
keeps all rows in the first table, even those with no matches. The +
syntax is harder to follow. The +
goes on the side that would get the NULL
values. However, to me, this seems less likely that the unmatched rows are in the assignments table.
If you have proper foreign key relationships, then all the assignments should have a correct person. I may not understand you data, however, and you might want to reverse your tables for what you are really trying to do.
EDIT:
As for overlaps, I would be inclined to use the simpler:
on dah.person_id = emp.person_id and
(dah.effective_end_date >= emp.date_from and
dah.effective_start_date <= emp.date_to
)
You can even write this using the archaic +
notation, if you like. Also note: these do not do exactly the same things. This will detect overlaps where one period is entirely embedded in another period.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With