यह अंतराल और द्वीपों की समस्या का एक रूपांतर है, प्रत्येक द्वीप में पंक्तियों की अधिकतम संख्या की अतिरिक्त जटिलता के साथ। यह थोड़ा लंबा-चौड़ा है लेकिन आप अनुक्रम क्रम के कारण समूहों की पहचान करके शुरू कर सकते हैं:
select t.*,
row_number() over (partition by "Description" order by "Start") as rn,
case when lag("SequentialOrder")
over (partition by "Description" order by "Start") < "SequentialOrder"
then 1 else 0 end as newblock
from test t
order by "Start";
Start Description MaximunRow SequentialOrder RN NEWBLOCK
--------- ----------- ---------- --------------- --- ----------
12-JUN-15 A 3 3 1 0
13-JUN-15 A 3 4 2 1
14-JUN-15 A 3 5 3 1
01-JUL-15 A 3 4 4 0
02-JUL-15 A 3 3 5 0
04-JUL-15 A 3 4 6 1
01-AUG-15 B 2 5 1 0
16-AUG-15 B 2 7 2 1
फिर आप एक पुनरावर्ती CTE का उपयोग कर सकते हैं (11gR2 से आगे) उसके आधार पर:
with u as (
select t.*,
row_number() over (partition by "Description" order by "Start") as rn,
case when lag("SequentialOrder")
over (partition by "Description" order by "Start") < "SequentialOrder"
then 1 else 0 end as newblock
from test t
),
r ("Start", "Description", "MaximunRow", "SequentialOrder", rn, blocknum,
pos, lastmaxrow) as (
select u."Start", u."Description", u."MaximunRow", u."SequentialOrder", u.rn,
1, 1, u."MaximunRow"
from u
where rn = 1
union all
select u."Start", u."Description", u."MaximunRow", u."SequentialOrder", u.rn,
case when r.pos = r.lastmaxrow or u.newblock = 0
then r.blocknum + 1 else r.blocknum end,
case when r.pos = r.lastmaxrow or u.newblock = 0
then 1 else r.pos + 1 end,
case when r.pos = r.lastmaxrow or u.newblock = 0
then r.lastmaxrow else u."MaximunRow" end
from r
join u on u."Description" = r."Description" and u.rn = r.rn + 1
)
select * from r
order by "Start";
Start Description MaximunRow SequentialOrder RN BLOCKNUM POS LASTMAXROW
--------- ----------- ---------- --------------- --- ---------- ---- ----------
12-JUN-15 A 3 3 1 1 1 3
13-JUN-15 A 3 4 2 1 2 3
14-JUN-15 A 3 5 3 1 3 3
01-JUL-15 A 3 4 4 2 1 3
02-JUL-15 A 3 3 5 3 1 3
04-JUL-15 A 3 4 6 3 2 3
01-AUG-15 B 2 5 1 1 1 2
16-AUG-15 B 2 7 2 1 2 2
यह एक blocknum
असाइन कर रहा है प्रत्येक पंक्ति में, एंकर सदस्य में प्रत्येक विवरण के लिए एक से शुरू होने के साथ, और पुनरावर्ती सदस्य में वृद्धि की जा रही है या तो newblock
शून्य है (एक अनुक्रम विराम का संकेत) या ब्लॉक में सदस्यों की संख्या पिछली अधिकतम है। (मेरे पास 'पिछला अधिकतम' के लिए तर्क बिल्कुल सही नहीं हो सकता है क्योंकि यह प्रश्न में स्पष्ट नहीं है।)
फिर आप विवरण और उत्पन्न ब्लॉक संख्या के आधार पर समूह बना सकते हैं:
with u as (
select t.*,
row_number() over (partition by "Description" order by "Start") as rn,
case when lag("SequentialOrder")
over (partition by "Description" order by "Start") < "SequentialOrder"
then 1 else 0 end as newblock
from test t
),
r ("Start", "Description", "MaximunRow", "SequentialOrder", rn, blocknum,
pos, lastmaxrow) as (
select u."Start", u."Description", u."MaximunRow", u."SequentialOrder", u.rn,
1, 1, u."MaximunRow"
from u
where rn = 1
union all
select u."Start", u."Description", u."MaximunRow", u."SequentialOrder", u.rn,
case when r.pos = r.lastmaxrow or u.newblock = 0
then r.blocknum + 1 else r.blocknum end,
case when r.pos = r.lastmaxrow or u.newblock = 0
then 1 else r.pos + 1 end,
case when r.pos = r.lastmaxrow or u.newblock = 0
then r.lastmaxrow else u."MaximunRow" end
from r
join u on u."Description" = r."Description" and u.rn = r.rn + 1
)
select min(r."Start") as "Start", max(r."Start") as "End", r."Description"
from r
group by r."Description", r.blocknum
order by r."Description", r.blocknum;
Start End Description
--------- --------- -----------
12-JUN-15 14-JUN-15 A
01-JUL-15 01-JUL-15 A
02-JUL-15 04-JUL-15 A
01-AUG-15 16-AUG-15 B
आपका नमूना डेटा अधिकतम पंक्तियों के विराम को ट्रिगर नहीं करता है क्योंकि आपके पास वैसे भी 3 से अधिक लंबा कोई क्रम नहीं है। कुछ अतिरिक्त डेटा के साथ:
Insert into TEST ("Start","Description","MaximunRow","SequentialOrder") values (to_date('15-JUN-15','DD-MON-RR'),'A',3,7);
Insert into TEST ("Start","Description","MaximunRow","SequentialOrder") values (to_date('16-JUN-15','DD-MON-RR'),'A',3,8);
Insert into TEST ("Start","Description","MaximunRow","SequentialOrder") values (to_date('17-JUN-15','DD-MON-RR'),'A',3,10);
Insert into TEST ("Start","Description","MaximunRow","SequentialOrder") values (to_date('18-JUN-15','DD-MON-RR'),'A',3,12);
Insert into TEST ("Start","Description","MaximunRow","SequentialOrder") values (to_date('19-JUN-15','DD-MON-RR'),'A',3,13);
वही क्वेरी मिलती है:
Start End Description
--------- --------- -----------
12-JUN-15 14-JUN-15 A
15-JUN-15 17-JUN-15 A
18-JUN-15 19-JUN-15 A
01-JUL-15 01-JUL-15 A
02-JUL-15 04-JUL-15 A
01-AUG-15 16-AUG-15 B
ताकि आप देख सकें कि यह क्रम परिवर्तन पर बंट रहा है और ब्लॉक में तीन पंक्तियों को हिट करने पर।
आप newblock
का उपयोग करने के बजाय सीधे केस स्टेटमेंट में अनुक्रमिक क्रम की तुलना करके, केवल पुनरावर्ती CTE से दूर हो सकते हैं, न कि पिछले मध्यवर्ती वाले से।; लेकिन rn
. होना अगली पंक्ति को खोजने के लिए अगली तारीख खोजने की कोशिश करने से आसान है क्योंकि वे सन्निहित नहीं हैं।