I would like to ask for your help for constructing a single ORACLE SQL statement:
using job table as below
Object | Operation | Time
A | Move | 12:01
B | Move | 12:02
C | Pickup | 12:03
D | Move | 12:04
B | Pickup | 12:05
to get the result table as below.
Object | Operation | Time | Cause
A | Move | 12:01 | C
B | Move | 12:02 | C
D | Move | 12:04 | B
This is to figure out which Pickup operation caused each Move operation.
"Cause" column must include Object of the pickup job record with smallest time right next to move operation.
I have some ideas as below but do not know how to.
-. It requires join statement between subquery for Move and subquery for Pickup
-. Subquery for Pickup must be partitioned by move record to be joined
-. Must select top record only from each partition of Pickup subquery
The advantage of a join includes that it executes faster. The retrieval time of the query using joins almost always will be faster than that of a subquery. By using joins, you can minimize the calculation burden on the database i.e., instead of multiple queries using one join query.
I won't leave you in suspense, between Joins and Subqueries, joins tend to execute faster. In fact, query retrieval time using joins will almost always outperform one that employs a subquery. The reason is that joins mitigate the processing burden on the database by replacing multiple queries with one join query.
SQL Joins and Subqueries. An SQL Join statement is used to combine data or rows from two or more tables based on a common field between them. A subquery is a query that is nested inside a SELECT , INSERT , UPDATE , or DELETE statement, or inside another subquery.
This is my try:
select m.object, m.operation, m.time,
max(p.object) keep (dense_rank first order by p.time) cause,
max(p.time) keep (dense_rank first order by p.time) cause_time
from a m
join a p on (p.time > m.time)
where m.operation = 'Move'
and p.operation = 'Pickup'
group by m.object, m.operation, m.time;
see SQLFiddle
I've put column time as number, this does not have any importance as it is sortable.
I've splitted the table in two, Moves and Pickups and the join is made on time, time of pickup
being greater than time of move
. (This type of join is not great on performance). Then I choose
the pickup with smallest time
(first
clause, with order by p.time
).
This is my try:
select object, operation, time, t.pobject
from a join
(select object pobject, time cur, lag(time,1, 0) over (order by time ) prev
from a
where operation = 'Pickup')t
on a.time > t.prev and a.time <= t.cur
where operation = 'Move';
Here is a sqlfiddle
There is one from old-school
select j1.Object, j1.Operation, j1.Time, substr(min(j2.Time || j2.Object), 6) Cause
from job j1, job j2
where j1.Operation like 'Move'
and j1.Time < j2.Time
and j2.Operation like 'Pickup'
group by j1.Object, j1.Operation, j1.Time
Here is SQLFiddle
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