Search code examples
oracle-databaseanalytic-functions

Finding a count of rows in an arbitrary date range using Oracle


The question I need to answer is this "What is the maximum number of page requests we have ever received in a 60 minute period?"

I have a table that looks similar to this:

date_page_requested      date;
page                     varchar(80);

I'm looking for the MAX count of rows in any 60 minute timeslice.

I thought analytic functions might get me there but so far I'm drawing a blank.

I would love a pointer in the right direction.


Solution

  • You have some options in the answer that will work, here is one that uses Oracle's "Windowing Functions with Logical Offset" feature instead of joins or correlated subqueries.

    First the test table:

    Wrote file afiedt.buf
    
      1  create table t pctfree 0 nologging as
      2  select date '2011-09-15' + level / (24 * 4) as date_page_requested
      3  from dual
      4* connect by level <= (24 * 4)
    SQL> /
    
    Table created.
    
    SQL> insert into t values (to_date('2011-09-15 11:11:11', 'YYYY-MM-DD HH24:Mi:SS'));
    
    1 row created.
    
    SQL> commit;
    
    Commit complete.
    

    T now contains a row every quarter hour for a day with one additional row at 11:11:11 AM. The query preceeds in three steps. Step 1 is to, for every row, get the number of rows that come within the next hour after the time of the row:

      1  with x as (select date_page_requested
      2          , count(*) over (order by date_page_requested
      3              range between current row
      4                  and interval '1' hour following) as hour_count
      5      from t)
    

    Then assign the ordering by hour_count:

      6  , y as (select date_page_requested
      7          , hour_count
      8          , row_number() over (order by hour_count desc, date_page_requested asc) as rn
      9      from x)
    

    And finally select the earliest row that has the greatest number of following rows.

     10  select to_char(date_page_requested, 'YYYY-MM-DD HH24:Mi:SS')
     11      , hour_count
     12  from y
     13* where rn = 1
    

    If multiple 60 minute windows tie in hour count, the above will only give you the first window.