views:

389

answers:

2

I've been working on a Stored Procedure that checks the time, then retrieves records going back over the last full 24 hour period between 8am and the previous 8am. So, for instance, assume that it's currently 10am. The stored procedure looks at the current time, notes that it is past 8am, and sets the query to run backwards 24 hours, from 8am today to 8a yesterday. If it were, say, 7am, the query would be set to check from 8am yesterday to 8am the day before. This was actually relatively simple to do. The SP is meant to be used to retrieve records for a report tracking jobs completed in the given time span.

However, they've come back at me and asked me to change the stored procedure such that the hour the report ends at, and the span of time checked, is configurable from the front-end of the site. I have this working for TimeSpans greater or equal to 24 hours, but am having trouble with spans under that. Here's what I have so far for my logic in the Stored Procedure -

-- Retrieves data on jobs that completed/completed with errors during a given time span.
DECLARE @Hour NVARCHAR(2)
DECLARE @TimeFrame NVARCHAR(2)
DECLARE @TimeSpan INTEGER

SET @TimeSpan = 24
SET @TimeFrame = 'AM'
SET @Hour = '08'

DECLARE @dateStart DateTime
DECLARE @dateEnd DateTime

IF @TimeSpan < 24 -- Our TimeSpan is under one full day.
    BEGIN
      IF GETDATE() > DATEADD(hh, 0, DATEDIFF(hh, 0, GETDATE())) + (@Hour + ':00:00 ' + @TimeFrame)
      BEGIN
       SET @dateStart = DATEADD(hh, 0, DATEDIFF(hh, 0, GETDATE() - (1 + @TimeSpan))) + (@Hour + ':00:00 ' + @TimeFrame)
       SET @dateEnd =  DATEADD(hh, 0, DATEDIFF(hh, 0, GETDATE())) + (@Hour + ':00:00 ' + @TimeFrame)
      END
     ELSE
      BEGIN
       SET @dateStart = DATEADD(hh, 0, DATEDIFF(hh, 0, GETDATE() - (2 + @TimeSpan))) + (@Hour + ':00:00 ' + @TimeFrame)
       SET @dateEnd =  DATEADD(hh, 0, DATEDIFF(hh, 0, GETDATE() - 1)) + (@Hour + ':00:00 ' + @TimeFrame)
      END
    END
ELSE -- Our TimeSpan is at least one full day.
    BEGIN
     IF GETDATE() > DATEADD(D, 0, DATEDIFF(D, 0, GETDATE())) + (@Hour + ':00:00 ' + @TimeFrame)
      BEGIN
       SET @dateStart = DATEADD(D, 0, DATEDIFF(D, 0, GETDATE() - (1 + (@TimeSpan/24)))) + (@Hour + ':00:00 ' + @TimeFrame)
       SET @dateEnd =  DATEADD(D, 0, DATEDIFF(D, 0, GETDATE())) + (@Hour + ':00:00 ' + @TimeFrame)
      END
     ELSE
      BEGIN
       SET @dateStart = DATEADD(D, 0, DATEDIFF(D, 0, GETDATE() - (2 + (@TimeSpan/24)))) + (@Hour + ':00:00 ' + @TimeFrame)
       SET @dateEnd =  DATEADD(D, 0, DATEDIFF(D, 0, GETDATE() - 1)) + (@Hour + ':00:00 ' + @TimeFrame)
      END
    END

@Hour, @TimeFrame and @TimeSpan are all parameters ready to be set by the report front-end, and default to '08', 'AM' and 24 respectively. I know that setting the day range works properly in the ELSE portion of the top-level if. I'm reasonably certain that the issue with setting the hour offset lies in how I'm using the DATEADD and DATEDIFF function here, but I haven't been able to figure out just where I'm making my miss step. Any help here would be greatly appreciated.

A: 

Why not just use a query like:

SELECT something
FROM aTable
WHERE timeCompleted BETWEEN @StartDate AND @EndDate

If you are concerned about the time being correct (i.e. the dates must be '01/01/1900 13:00:00' or something like that) just pass in the date by itself and add the time as a function in the SQL.

If this is not what you are intending please include more of the SQL so that we have a better understanding of what you are trying to accomplish.

jellomonkey
That's actually what the select statement following the above amounts to. The select statement is simple.The problem is in correctly calculating the correct date to determine the range against. Selecting a range in days is easy, and the code already works to that effect. However, they want the same report to be able to select a range of mere hours, and that is where the problem lies. Whether it's done in the VB backend, or SQL Server, at some point I have to calculate the exact time range that's being selected.
Clyde
A: 
-- convert the required end hour to 24 hour format
DECLARE @EndHour INT
SET @EndHour = CASE WHEN @TimeFrame = 'AM' THEN @Hour ELSE @Hour + 12 END

-- set @DateEnd to the date-only portion of the current datetime
-- ie, the time portion will be set to 00:00:00
SET @DateEnd = DATEADD(day, 0, DATEDIFF(day, 0, GETDATE()))

-- add the required end hour
SET @DateEnd = DATEADD(hour, @EndHour, @DateEnd)

-- if @DateEnd is in the future then subtract 24 hours from it
IF @DateEnd > GETDATE()
   SET @DateEnd = DATEADD(hour, -24, @DateEnd)

-- set @DateStart by subtracting the required timespan from @DateEnd
SET @DateStart = DATEADD(hour, -@TimeSpan, @DateEnd)
LukeH
Ah, that works great, once I changed hour over to an integer instead of the nvarchar. Many thanks, the help is greatly appreciated!
Clyde
I have to stand corrected - it's a lot less complex than the nested if structure, so is already a great improvement, but it's still got the same problem. The shortest period of time that it'll select between is 24 hours. If it's under 24 hours, regardless of what I request, it still comes up with that 1 day window.
Clyde
@Clyde, My code works correctly, as described (you can do "SELECT @DateStart, @DateEnd" to verify this). I suspect the problem is elsewhere in your code, probably in the query where you actually use the calculated start and end dates. Can you post that query?
LukeH
Actually, that's exactly how I was checking the apparent time span issue last night. That said, I just went back in and tried it again - and it's bringing up the correct time span now. I'm pretty sure at this point that I was testing the wrong code - too long up, and juggling too many things at once, with way too many tabs open in my manager, heh... Thank you again for the help.
Clyde