यह एक अंतराल और द्वीप समस्या है, लेकिन द्वीपों को REQ
. द्वारा परिभाषित किया जा रहा है लेन-देन इसे कुछ की तुलना में थोड़ा अधिक जटिल बनाता है।
आपको जो चाहिए वह प्राप्त करने के लिए आप नेस्टेड लीड और लैग फ़ंक्शंस और कुछ हेरफेर का उपयोग कर सकते हैं:
select distinct item,
coalesce(start_tran,
lag(start_tran) over (partition by item order by timestamp)) as start_tran,
coalesce(end_tran,
lead(end_tran) over (partition by item order by timestamp)) as end_tran,
coalesce(end_time,
lead(end_time) over (partition by item order by timestamp))
- coalesce(start_time,
lag(start_time) over (partition by item order by timestamp)) as time
from (
select item, timestamp, start_tran, start_time, end_tran, end_time
from (
select item,
timestamp,
case when lag_tran is null or transaction like 'REQ%'
then transaction end as start_tran,
case when lag_tran is null or transaction like 'REQ%'
then timestamp end as start_time,
case when lead_tran is null or lead_tran like 'REQ%'
then transaction end as end_tran,
case when lead_tran is null or lead_tran like 'REQ%'
then timestamp end as end_time
from (
select item, transaction, timestamp,
lag(transaction)
over (partition by item order by timestamp) as lag_tran,
lead(transaction)
over (partition by item order by timestamp) as lead_tran
from transactions
)
)
where start_tran is not null or end_tran is not null
)
order by item, start_tran;
आइटम 1 और 2 के लिए दूसरे चक्र के लिए अतिरिक्त रिकॉर्ड के साथ जो दे सकता है:
ITEM START_TRAN END_TRAN TIME
---------- ---------- ---------- -----------
1 REQ-A PICKUP 0 1:53:30.0
1 REQ-E PICKUP 0 1:23:30.0
2 REQ-B MAIL 0 0:24:13.0
2 REQ-F REQ-F 0 0:0:0.0
3 REQ-C PICKUP 0 1:46:30.0
4 REQ-D PULL 0 0:23:59.0
5 REQ-A PICKUP 0 1:43:59.0
SQL Fiddle सभी मध्यवर्ती चरण दिखा रहा है।
यह उतना डरावना नहीं है जितना पहली नज़र में लग सकता है। अंतरतम क्वेरी कच्चा डेटा लेती है और लीड और लैग लेनदेन के लिए एक अतिरिक्त कॉलम जोड़ती है। आइटम-1 रिकॉर्ड का केवल पहला सेट लेना जो होगा:
ITEM TRANSACTION TIMESTAMP LAG_TRAN LEAD_TRAN
---------- ----------- ------------------------ ---------- ----------
1 REQ-A 2014-07-31T09:51:32Z PULL
1 PULL 2014-07-31T10:22:21Z REQ-A TRANSFER
1 TRANSFER 2014-07-31T10:22:23Z PULL ARRIVE
1 ARRIVE 2014-07-31T11:45:01Z TRANSFER PICKUP
1 PICKUP 2014-07-31T11:45:02Z ARRIVE REQ-E
नोटिस REQ-E
अंतिम lead_tran
. के रूप में पॉप अप हो रहा है ? यह पहला transaction
है इस मद के लिए रिकॉर्ड के दूसरे चक्र के लिए, और बाद में उपयोगी होने जा रहा है। क्वेरी का अगला स्तर उन लीड और लैग मानों का उपयोग करता है और REQ
. का व्यवहार करता है प्रारंभ और अंत मार्कर के रूप में मान, और उस जानकारी का उपयोग प्रत्येक चक्र के पहले और अंतिम रिकॉर्ड को छोड़कर सब कुछ रद्द करने के लिए करता है।
ITEM TIMESTAMP START_TRAN START_TIME END_TRAN END_TIME
---------- ------------------------ ---------- ------------------------ ---------- ------------------------
1 2014-07-31T09:51:32Z REQ-A 2014-07-31T09:51:32Z
1 2014-07-31T10:22:21Z
1 2014-07-31T10:22:23Z
1 2014-07-31T11:45:01Z
1 2014-07-31T11:45:02Z PICKUP 2014-07-31T11:45:02Z
क्वेरी का अगला स्तर उन पंक्तियों को हटा देता है जो प्रारंभ या अंत का प्रतिनिधित्व नहीं कर रही हैं (या दोनों - देखें REQ-F
Fiddle में) क्योंकि हमें उनमें कोई दिलचस्पी नहीं है:
ITEM TIMESTAMP START_TRAN START_TIME END_TRAN END_TIME
---------- ------------------------ ---------- ------------------------ ---------- ------------------------
1 2014-07-31T09:51:32Z REQ-A 2014-07-31T09:51:32Z
1 2014-07-31T11:45:02Z PICKUP 2014-07-31T11:45:02Z
अब हमारे पास प्रत्येक चक्र के लिए पंक्तियों के जोड़े हैं (या REQ-F
. के लिए एक पंक्ति ) अंतिम स्तर रिक्त स्थान को भरने के लिए फिर से सीसा और अंतराल का उपयोग करता है; अगर start_tran
शून्य है तो यह एक अंत-पंक्ति है और हमें पिछली पंक्ति के प्रारंभ डेटा का उपयोग करना चाहिए; अगर end_tran
शून्य है तो यह एक प्रारंभ-पंक्ति है और हमें अगली पंक्ति के अंतिम डेटा का उपयोग करना चाहिए।
ITEM START_TRAN START_TIME END_TRAN END_TIME TIME
1 REQ-A 2014-07-31T09:51:32Z PICKUP 2014-07-31T11:45:02Z 0 1:53:30.0
1 REQ-A 2014-07-31T09:51:32Z PICKUP 2014-07-31T11:45:02Z 0 1:53:30.0
यह दोनों पंक्तियों को समान बनाता है, इसलिए distinct
डुप्लिकेट हटा देता है।