1

I've seen some examples of this done, but I can't seem to get it working right..

I have a table as follows

ID | FK | Location | StartDateTime | EndDateTime

It is a stay segment table. The FK relates to the parent record, and the ID relates to each stay segment. I want to split each stay segment into hourly segments.. So as follows; If the start time is 10:23 then the first record will be

1 | 254 | Loc1 | 10:23 | 10:59
1 | 254 | Loc1 | 11:00 | 11:59
1 | 254 | Loc1 | 12:00 | 12:45
2 | 254 | Loc2 | 12:45 | 12:50

Your help is appreciated.

Matt
  • 4,140
  • 9
  • 40
  • 64

1 Answers1

1

There may be various approaches to solving this, like a recursive CTE (if you are on '2005+ version), a numbers table, a calendar table (which may also be considered as special case numbers table method).

The following example uses a system table called master..spt_values acting as a plain old numbers table:

WITH sampledata (ID, FK, Location, StartDateTime, EndDateTime) AS (
  SELECT 1, 254, 'Loc1', CAST('20110910 10:23' AS datetime), CAST('20110910 12:45' AS datetime) UNION ALL
  SELECT 2, 254, 'Loc2', CAST('20110910 12:45' AS datetime), CAST('20110910 12:50' AS datetime)
),
hourly AS (
  SELECT
    d.ID,
    d.FK,
    d.Location,
    d.StartDateTime,
    d.EndDateTime,
    HourlyStartDateTime =               DATEADD(HOUR, DATEDIFF(HOUR, 0, d.StartDateTime) + v.number,     0),
    HourlyEndDateTime = DATEADD(MS, -3, DATEADD(HOUR, DATEDIFF(HOUR, 0, d.StartDateTime) + v.number + 1, 0))
  FROM sampledata d
    INNER JOIN master..spt_values v ON v.type = 'P'
     AND v.number BETWEEN 0 AND DATEDIFF(HOUR, d.StartDateTime, d.EndDateTime)
)
SELECT
  ID,
  FK,
  Location,
  StartDateTime = CASE WHEN StartDateTime < HourlyStartDateTime THEN HourlyStartDateTime ELSE StartDateTime END,
  EndDateTime   = CASE WHEN EndDateTime   > HourlyEndDateTime   THEN HourlyEndDateTime   ELSE EndDateTime   END
FROM hourly

Because I'm not sure about the time granulation in your data, I defined HourlyEndDateTime as "3 milliseconds to the end of the current hour". You may well change it to "1 second or 1 minute to the end of the hour".

Community
  • 1
  • 1
Andriy M
  • 76,112
  • 17
  • 94
  • 154