Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8893585
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T23:17:05+00:00 2026-06-14T23:17:05+00:00

The scenario is users specify when they are available , these specified times can

  • 0

The scenario is users specify when they are available, these specified times can overlap each other. I’m trying to get the total time they are available for. Example with SQL Fiddle:

--Available--
ID  userID  availStart          availEnd
1   456     '2012-11-19 16:00'  '2012-11-19 17:00'
2   456     '2012-11-19 16:00'  '2012-11-19 16:50'
3   456     '2012-11-19 18:00'  '2012-11-19 18:30'
4   456     '2012-11-19 17:30'  '2012-11-19 18:10'
5   456     '2012-11-19 16:00'  '2012-11-19 17:10'
6   456     '2012-11-19 16:00'  '2012-11-19 16:50'

The output should be 130 minutes:

1: 60
2: 0 as falls inside 1
3: 30
4: 30 as the last 10 mins is covered by 3
5: 10 as first 60 mins is covered by 1
6: 0 as falls inside 1

I can get the total overlapping minutes, however this is more than the SUM of the available minutes:

SQL Fiddle

Any ideas how I can achieve this?

EDIT 21st Nov 12: Thanks so far for everyone’s solutions – in a way I’m happy to see this wasn’t an ‘easy’ query to write.

EDIT 23rd Nov 12: This is all great work. Internally here we’re thinking it might be best to ensure users cannot enter overlapping times (eg forcing them to amend an existing entry)!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-14T23:17:06+00:00Added an answer on June 14, 2026 at 11:17 pm

    Gordon Linoff has a CTE based answer

    I’ve done some performance analysis on all the working algorithms
    Blank values mean it took too long. This is tested on a single Core i7 X920 @2GHz chip, backed by a couple of SSDs. The only index created was a cluster on UserID, AvailStart. If you think you can improve any of the performance, let me know.

    This CTE version was worse than linear, SQL Server can’t do the RN = RN + 1 join in an efficient way. I rectified this with a hybrid approach below, where I save and index the first CTE into a table variable. This still takes ten times as much IO as the cursor based approach.

    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

    After doing some performance analysis, here’s a hybrid CTE/table variable version that performs better than anything except the cursor based approach

    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

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm not familiar on how forms work. Example Scenario Lets say users can create
The scenario is I want to get the users who has less than 2
The following scenario is given: /Collection1 (a number of users are subscribed to this
I'm having a problem in getting an array of a users ratings. The scenario
Scenario: User X1 logged in. He can not be logged again. up to previous
I am trying to relax my website's session expiration policy so that the users
I'm modelling a scenario with Users and Tools , where a Tool is owned
Here is a common scenario I Have these Entity User UserId UserName ... UserQuestion
Is there any way that you can specify in Fluent NHibernate to leave out
I have the following two table scenario: users id groups 1 1,2,3 2 2,3

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.