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

अनेक दिनांक सीमाओं के बीच मिनटों का योग

Gordon Linoff एक CTE आधारित उत्तर है

मैंने कुछ प्रदर्शन विश्लेषण किया है सभी कार्यशील एल्गोरिथम पर रिक्त मानों का अर्थ है कि इसमें बहुत अधिक समय लगा। इसका परीक्षण सिंगल कोर i7 X920 @2GHz चिप पर किया जाता है, जो कुछ SSD द्वारा समर्थित है। बनाया गया एकमात्र इंडेक्स UserID, AvailStart पर एक क्लस्टर था। अगर आपको लगता है कि आप किसी भी प्रदर्शन में सुधार कर सकते हैं, तो मुझे बताएं।

यह सीटीई संस्करण रैखिक से भी बदतर था, एसक्यूएल सर्वर आरएन =आरएन + 1 को एक कुशल तरीके से शामिल नहीं कर सकता। मैंने इसे नीचे एक हाइब्रिड दृष्टिकोण के साथ सुधारा है, जहां मैं पहले सीटीई को तालिका चर में सहेजता हूं और अनुक्रमित करता हूं। यह अभी भी कर्सर आधारित दृष्टिकोण से दस गुना अधिक IO लेता है।

With OrderedRanges as (
  Select
    Row_Number() Over (Partition By UserID Order By AvailStart) AS RN,
    AvailStart,
    AvailEnd
  From
    dbo.Available
  Where
    UserID = 456
),
AccumulateMinutes (RN, Accum, CurStart, CurEnd) as (
  Select
    RN, 0, AvailStart, AvailEnd
  From
    OrderedRanges
  Where 
    RN = 1
  Union All
  Select
    o.RN, 
    a.Accum + Case When o.AvailStart <= a.CurEnd Then
        0
      Else 
        DateDiff(Minute, a.CurStart, a.CurEnd)
      End,
    Case When o.AvailStart <= a.CurEnd Then 
        a.CurStart
      Else
        o.AvailStart
      End,
    Case When o.AvailStart <= a.CurEnd Then
        Case When a.CurEnd > o.AvailEnd Then a.CurEnd Else o.AvailEnd End
      Else
        o.AvailEnd
      End
  From
    AccumulateMinutes a
        Inner Join 
    OrderedRanges o On 
        a.RN = o.RN - 1
)

Select Max(Accum + datediff(Minute, CurStart, CurEnd)) From AccumulateMinutes 

http://sqlfiddle.com/#!6/ac021/2

कुछ प्रदर्शन विश्लेषण करने के बाद, यहां एक हाइब्रिड सीटीई/टेबल वैरिएबल संस्करण है जो कर्सर आधारित दृष्टिकोण को छोड़कर किसी भी चीज़ से बेहतर प्रदर्शन करता है

Create Function dbo.AvailMinutesHybrid(@UserID int) Returns Int As
Begin

Declare @UserRanges Table (
  RN int not null primary key, 
  AvailStart datetime, 
  AvailEnd datetime
)
Declare @Ret int = Null

;With OrderedRanges as (
  Select
    Row_Number() Over (Partition By UserID Order By AvailStart) AS RN,
    AvailStart,
    AvailEnd
  From
    dbo.Available
  Where
    UserID = @UserID
)
Insert Into @UserRanges Select * From OrderedRanges


;With AccumulateMinutes (RN,Accum, CurStart, CurEnd) as (
  Select
    RN, 0, AvailStart, AvailEnd
  From
    @UserRanges
  Where 
    RN = 1
  Union All
  Select
    o.RN, 
    a.Accum + Case When o.AvailStart <= a.CurEnd Then
        0
      Else 
        DateDiff(Minute, a.CurStart, a.CurEnd)
      End,
    Case When o.AvailStart <= a.CurEnd Then 
        a.CurStart
      Else
        o.AvailStart
      End,
    Case When o.AvailStart <= a.CurEnd Then
        Case When a.CurEnd > o.AvailEnd Then a.CurEnd Else o.AvailEnd End
      Else
        o.AvailEnd
      End
  From
    AccumulateMinutes a
        Inner Join 
    @UserRanges o On 
        a.RN + 1 = o.RN
)

Select 
  @Ret = Max(Accum + datediff(Minute, CurStart, CurEnd)) 
From 
  AccumulateMinutes 
Option
  (MaxRecursion 0)

Return @Ret

End

http://sqlfiddle.com/#!6/bfd94



  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 सर्वर तालिका बनाना

  3. टी-एसक्यूएल में गोल मिलीसेकंड

  4. SQL सर्वर कर्सर के साथ Salesforce डेटा अपडेट कर रहा है

  5. संग्रहीत प्रक्रिया के अंदर डेटाबेस का प्रयोग करें