2012-12-18 4 views
6

Chciałbym prosić o pomoc w konstruowaniu pojedynczej instrukcji Oracle SQL:wybierając górną płytę w Oracle dołączyć oświadczenie między podzapytaniami

wykorzystaniem tabeli pracy jako poniżej

Object | Operation | Time 
A  | Move  | 12:01 
B  | Move  | 12:02 
C  | Pickup | 12:03 
D  | Move  | 12:04 
B  | Pickup | 12:05 

aby uzyskać tabelę wynikową jako poniżej.

Object | Operation | Time | Cause 
A  | Move  | 12:01 | C 
B  | Move  | 12:02 | C 
D  | Move  | 12:04 | B 

Umożliwia to zorientowanie się, która operacja pobrania spowodowała operację przenoszenia.
Kolumna "Przyczyna" musi zawierać obiekt rekordu zadania odbioru z najmniejszym czasem zaraz obok operacji przenoszenia.

Mam kilka pomysłów jak poniżej, ale nie wiem jak.
-. Wymaga instrukcji join między podzapytaniem dla Move i podzapytaniem dla Pickup
-. Podzapytanie dla odbioru musi zostać podzielone na partycje według rekordu przeniesienia, który ma zostać dołączony:
-. Należy wybrać górną płytę tylko z każdej partycji Pickup podzapytaniu

+0

nie będzie 'minimalna (colName)' rozwiązać swoje trzecie wymaganie? Powodzenia. – shellter

+0

Typ danych kolumny "Czas"? – TechDo

+0

@shellter musi być MIN() za każdy rekord ruchu –

Odpowiedz

4

To moja próba:

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; 

zobaczyć SQLFiddle

Włożyłam czas kolumn jako liczby, to nie ma żadnego znaczenia, jak to można sortować.

Podzielam stół na dwie części, ruchy i odbiory, a łączenie jest wykonywane na czas, czas pickup jest większy niż czas move. (Ten typ łączenia nie jest dobry pod względem wydajności). Następnie I choose odbiór z najmniejszą klauzulą ​​time (first, z order by p.time).

+0

Dziękuję za nie tylko instrukcję SQL, ale także życzliwe wyjaśnienia :) –

4

To moja próba:

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

+0

Przyjemne dołączenie, +1 ode mnie :) –

+0

+1, ale wciąż potrzebuję więcej nauki, aby zrozumieć, jak to działa :) –

+0

@ShonerSul, Objaśnienie: wybór wewnętrzny pobiera tylko linie 'Pickup' i używa funkcji 'lag' do uzyskania czasu poprzedniego rekordu (więc w zasadzie teraz mam czas rozpoczęcia i czas zakończenia wszystkich ruchów). Wtedy mogę dołączyć do niego z wszystkimi rekordami "Przenieś" –

4

Jest jednym z 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 

Oto SQLFiddle

+0

+1 za używanie sqlfiddle jako dowód – booyaa

+0

jak ten, bez użycia fantazyjnych funkcji "zależnych od platformy". Czy ktoś może to zrobić za pomocą czystego SQL? – cha

+0

@cha Jest całkiem czysty :) Zamień substr() na podłańcuch(), a otrzymasz rozwiązanie ANSI SQL. – knagaev

Powiązane problemy