4

Let's say my table looks like this:

Sessions
start_dts (datetime)
end_dts (datetime)

and the data looks like this:

start_dts             end_dts
12/25/2011 01:55:00   12/25/2011 03:30:00

I need the query results to look like this:

Date          Hour    MinutesOnline
12/25/2011    0       0
12/25/2011    1       5
12/25/2011    2       60
12/25/2011    3       30
... (every hour of the date range being queried)

Is this even possible with a single query?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
E-Madd
  • 4,414
  • 5
  • 45
  • 77

2 Answers2

1

Here is a pretty good start. This will work for any date/time range. However, it has one main prerequisite: You need to create an intervals table with a dt_hr datetime field which contains all the intervals you are scanning over.

Ex: '2011-12-25 00:00:00',
    '2011-12-25 01:00:00',
    '2011-12-25 02:00:00',
    '2011-12-25 03:00:00',
          . . .
    '2011-12-25 23:00:00'

-

SELECT DATE_FORMAT(intervals.dt_hr,'%m/%d/%Y') AS Date,
       EXTRACT(HOUR FROM intervals.dt_hr) AS Hour,
       CASE 
          WHEN intervals.dt_hr > TIMESTAMPADD(HOUR,HOUR(s2.start_dts), DATE(s2.start_dts)) 
               AND intervals.dt_hr < TIMESTAMPADD(HOUR,HOUR(s2.end_dts), DATE(s2.end_dts))
            THEN 60
          WHEN intervals.dt_hr = TIMESTAMPADD(HOUR,HOUR(s2.start_dts), DATE(s2.start_dts)) 
               AND intervals.dt_hr < TIMESTAMPADD(HOUR,HOUR(s2.end_dts), DATE(s2.end_dts))
            THEN 60 - EXTRACT(MINUTE FROM s2.start_dts)
          WHEN intervals.dt_hr = TIMESTAMPADD(HOUR,HOUR(s2.end_dts), DATE(s2.end_dts))
               AND intervals.dt_hr > TIMESTAMPADD(HOUR,HOUR(s2.start_dts), DATE(s2.start_dts)) 
            THEN EXTRACT(MINUTE FROM s2.end_dts)
          WHEN intervals.dt_hr = TIMESTAMPADD(HOUR,HOUR(s2.start_dts), DATE(s2.start_dts)) 
               AND intervals.dt_hr = TIMESTAMPADD(HOUR,HOUR(s2.end_dts), DATE(s2.end_dts))
            THEN EXTRACT(MINUTE FROM s2.end_dts) - EXTRACT(MINUTE FROM s2.start_dts)
          ELSE 0
       END AS MinutesOnLine
FROM intervals
LEFT JOIN sessions s2 
  ON intervals.dt_hr >= TIMESTAMPADD(HOUR,HOUR(s2.start_dts), DATE(s2.start_dts)) 
    AND intervals.dt_hr <= TIMESTAMPADD(HOUR,HOUR(s2.end_dts), DATE(s2.end_dts))

To generate the intervals table, you could create a stored procedure which creates a temporary table with a date_hour sequence. See Get a list of dates between two dates for a way to do this.

Community
  • 1
  • 1
Holger Brandt
  • 4,324
  • 1
  • 20
  • 35
0

More of a big comment than answer.

Not good enough with MySQL to do it but a CTE to come up with a set of datetimes between start_dts and end_dts so you get

startTime           endTime     
12/25/2011 01:00:00 12/25/2011 02:00:00
12/25/2011 02:00:00 12/25/2011 03:00:00
12/25/2011 03:00:00 12/25/2011 04:00:00

joined back to session On CT.EndTime < DateAdd(sessions.end_dts, INTERVAL 1 HOUR)

and then Hour(CTS.StartTime) - Hour(sessions.start_dts) and modulus of the time difference in minutes beteen cte.endtime and start_dts

maybe...

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39