tags:

views:

16

answers:

2

I have a field called dPostTime, which has the date and time stored of an entry.

If I wanted to create a page that showed me the number of entries per hour, would I need to have 24 queries, one for each hour, or what's the best way to do this.

I'd like the chart to appear as follows:

5-6pm - 24 posts
6-7pm - 56 posts
7-8pm - 34 posts
8-9pm - 35 posts

etc......

Thanks!

A: 
  SELECT COUNT(*),
         HOUR(`dPostTime`) AS `hr`
    FROM `table`
GROUP BY `hr`

After that in php format hr to be equal 'hr - 1' - hr

zerkms
Only issue I see is if the OP wants to see that there's a zero count, because there aren't values for the hour in the column.
OMG Ponies
+1  A: 

MySQL doesn't have recursive functionality, so you're left with using the NUMBERS table trick -

  1. Create a table that only holds incrementing numbers - easy to do using an auto_increment:

    DROP TABLE IF EXISTS `example`.`numbers`;
    CREATE TABLE  `example`.`numbers` (
      `id` int(10) unsigned NOT NULL auto_increment,
       PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
  2. Populate the table using:

    INSERT INTO NUMBERS
      (id)
    VALUES
      (NULL)
    

    ...for as many values as you need.

  3. Use DATE_ADD to construct a list of dates, increasing the days based on the NUMBERS.id value. Replace "2010-01-01" and "2010-01-02" with your respective start and end dates (but use the same format, YYYY-MM-DD HH:MM:SS) -

    SELECT x.dt
      FROM (SELECT DATE_FORMAT(DATE_ADD('2010-01-01', INTERVAL (n.id - 1) HOUR), '%H:%i') AS dt
              FROM numbers n
             WHERE DATE_ADD('2010-01-01', INTERVAL (n.id - 1) HOUR) <= '2010-01-02' ) x
    
  4. LEFT JOIN onto your table of data based on the datetime portion.

       SELECT x.dt,
              COALESCE(COUNT(a.dPostTime), 0) AS numPerHour
         FROM (SELECT DATE_FORMAT(DATE_ADD('2010-01-01', INTERVAL (n.id - 1) HOUR), '%H') AS dt
                 FROM numbers n
                WHERE DATE_ADD('2010-01-01', INTERVAL (n.id - 1) HOUR) <= '2010-01-02' ) x x
    LEFT JOIN YOUR_TABLE a ON DATE_FORMAT(a.dPostTime, '%H') = x.dt 
     GROUP BY x.dt
     ORDER BY x.dt
    

Why Numbers, not Dates?

Simple - dates can be generated based on the number, like in the example I provided. It also means using a single table, vs say one per data type.

OMG Ponies
By recursive functionality, do you mean that MySQL cannot use a Connect by level like Oracle can? I have had this exact question answered for Oracle: http://stackoverflow.com/questions/3455739/how-to-select-records-grouped-by-the-hour-of-the-day-including-hours-that-have-no
Cyntech
@Cyntech: Correct, `CONNECT BY` is Oracle specific hierarchical query syntax. The recursive WITH is now ANSI standard, but Oracle didn't support it until 11gR2--in Oracle's defense, they've had `CONNECT BY` since v2.
OMG Ponies
Thanks for this. Is this the only way to go about this? I have a single field that captures the date and time. I was going to use PHP to display this in a chart
BigMike
@BigMike: You need to generate a sequential list of hours to LEFT JOIN against. If it's a one time affair, use UNION statements to derive the table you need.
OMG Ponies
Thanks, could you explain #2 again? how many numbers do I need?
BigMike
@BigMike: You'd need to run the INSERT statement 24 -- one for every hour in the day.
OMG Ponies