Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQL अवधि समय गणना

मैंने कई मौकों पर ऐसा ही कुछ किया है। अनिवार्य रूप से, एक जटिल क्रम के भीतर अलगाव के आधार पर समूह बनाना। इस समस्या के संबंध में मेरे द्वारा उपयोग किए जाने वाले दृष्टिकोण की मूल बातें इस प्रकार हैं:

  1. रुचि की सभी समय श्रेणियों की तालिका बनाएं।
  2. रुचि की समय-सीमा के प्रत्येक समूह के लिए आरंभिक समय ढूंढें।
  3. रुचि के प्रत्येक समूह के लिए समाप्ति समय खोजें।
  4. प्रारंभ और समाप्ति समय को समय सीमाओं और समूह की सूची में शामिल करें।

या, अधिक विवरण में:(इनमें से प्रत्येक चरण एक बड़े CTE का हिस्सा हो सकता है, लेकिन मैंने पढ़ने में आसानी के लिए इसे अस्थायी तालिकाओं में तोड़ दिया है...)

चरण 1:ब्याज की सभी समय सीमाओं की सूची खोजें (मैंने @Brad द्वारा लिंक की गई विधि के समान एक विधि का उपयोग किया)। नोट:जैसा कि @Manfred Sorg ने बताया, यह मानता है कि बस के डेटा में कोई "गायब सेकंड" नहीं हैं। यदि टाइमस्टैम्प में कोई विराम है, तो यह कोड एकल श्रेणी को दो (या अधिक) भिन्न श्रेणियों के रूप में व्याख्यायित करेगा।

;with stopSeconds as (
  select BusID, BusStopID, TimeStamp,
         [date] = cast(datediff(dd,0,TimeStamp) as datetime),
         [grp] = dateadd(ss, -row_number() over(partition by BusID order by TimeStamp), TimeStamp)
  from #test
  where BusStopID is not null
)
select BusID, BusStopID, date,
       [sTime] = dateadd(ss,datediff(ss,date,min(TimeStamp)), 0),
       [eTime] = dateadd(ss,datediff(ss,date,max(TimeStamp)), 0),
       [secondsOfStop] = datediff(ss, min(TimeStamp), max(Timestamp)),
       [sOrd] = row_number() over(partition by BusID, BusStopID order by datediff(ss,date,min(TimeStamp))),
       [eOrd] = row_number() over(partition by BusID, BusStopID order by datediff(ss,date,max(TimeStamp)))
into #ranges
from stopSeconds
group by BusID, BusStopID, date, grp

चरण 2:प्रत्येक स्टॉप के लिए जल्द से जल्द समय खोजें

select this.BusID, this.BusStopID, this.sTime minSTime,
       [stopOrder] = row_number() over(partition by this.BusID, this.BusStopID order by this.sTime)
into #starts
from #ranges this
  left join #ranges prev on this.BusID = prev.BusID
                        and this.BusStopID = prev.BusStopID
                        and this.sOrd = prev.sOrd+1
                        and this.sTime between dateadd(mi,-10,prev.sTime) and dateadd(mi,10,prev.sTime)
where prev.BusID is null

चरण 3:प्रत्येक स्टॉप के लिए नवीनतम समय खोजें

select this.BusID, this.BusStopID, this.eTime maxETime,
       [stopOrder] = row_number() over(partition by this.BusID, this.BusStopID order by this.eTime)
into #ends
from #ranges this
  left join #ranges next on this.BusID = next.BusID
                        and this.BusStopID = next.BusStopID
                        and this.eOrd = next.eOrd-1
                        and this.eTime between dateadd(mi,-10,next.eTime) and dateadd(mi,10,next.eTime)
where next.BusID is null

चरण 4:सब कुछ एक साथ मिलाएं

select r.BusID, r.BusStopID,
       [avgLengthOfStop] = avg(datediff(ss,r.sTime,r.eTime)),
       [earliestStop] = min(r.sTime),
       [latestDepart] = max(r.eTime)
from #starts s
  join #ends e on s.BusID=e.BusID
              and s.BusStopID=e.BusStopID
              and s.stopOrder=e.stopOrder
  join #ranges r on r.BusID=s.BusID
                and r.BusStopID=s.BusStopID
                and r.sTime between s.minSTime and e.maxETime
                and r.eTime between s.minSTime and e.maxETime
group by r.BusID, r.BusStopID, s.stopOrder
having count(distinct r.date) > 1 --filters out the "noise"

अंत में, पूर्ण होने के लिए, साफ-सफाई करें:

drop table #ends
drop table #starts
drop table #ranges


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर में एक-से-शून्य-या-एक संबंध लागू करना

  2. SQL सर्वर प्रदर्शन टॉप CPU क्वेरी -2

  3. आप कैसे निर्धारित करते हैं कि SQL टेबल्स में प्रोग्रामेटिक रूप से पहचान कॉलम क्या है?

  4. SQL सर्वर स्केलर-मूल्यवान फ़ंक्शन धीमे क्यों हो जाते हैं?

  5. किसी दृश्य में प्रयुक्त उपनाम का वास्तविक स्तंभ नाम ज्ञात कीजिए?