Нахождение количества строк в произвольном диапазоне дат с использованием Oracle - PullRequest
2 голосов
/ 17 сентября 2011

Мне нужно ответить на вопрос: «Каково максимальное количество запросов страниц, которые мы когда-либо получали за 60-минутный период?»

У меня есть таблица, похожая на эту:

date_page_requested      date;
page                     varchar(80);

Я ищу максимальное количество строк в любом 60-минутном временном интервале.

Я думал, что аналитические функции могут помочь мне, но пока я рисую пробел.

Мне бы хотелось указатель в правильном направлении.

Ответы [ 5 ]

2 голосов
/ 17 сентября 2011

В ответе есть несколько вариантов, которые будут работать, вот тот, который использует функцию Oracle « Windowing с логическим смещением » вместо соединений или коррелированных подзапросов.

Первая таблица испытаний:

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 теперь содержит строку каждый четверть часа в течение дня с одной дополнительной строкой в ​​11:11:11. Запрос выполняется в три этапа. Шаг 1 состоит в том, чтобы получить для каждой строки число строк, приходящих в течение следующего часа после времени строки:

  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)

Затем назначьте порядок по часам:

  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)

И, наконец, выберите самую раннюю строку с наибольшим количеством следующих строк.

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

Если несколько часов по 60 минутам связаны в счетчике часов, вышеприведенное даст вам только первое окно.

0 голосов
/ 17 сентября 2011
WITH ranges AS
    ( SELECT
          date_page_requested          AS StartDate,
          date_page_requested + (1/24) AS EndDate,
          ROWNUMBER() OVER(ORDER BY date_page_requested) AS RowNo 
      FROM 
          @Table
    ) 

SELECT 
    a.StartDate                 AS StartDate,
    MAX(b.RowNo) - a.RowNo + 1  AS Tally 
FROM 
    ranges a
  JOIN
    ranges b 
      ON  a.StartDate <= b.StartDate
      AND b.StartDate < a.EndDate
GROUP BY a.StartDate
       , a.RowNo
ORDER BY Tally DESC

или:

WITH ranges AS
    ( SELECT
          date_page_requested          AS StartDate,
          date_page_requested + (1/24) AS EndDate,
          ROWNUMBER() OVER(ORDER BY date_page_requested) AS RowNo 
      FROM 
          @Table
    ) 

SELECT 
    a.StartDate                      AS StartDate,
    ( SELECT MIN(b.RowNo) - a.RowNo  
      FROM ranges b
      WHERE b.StartDate > a.EndDate
    )                                AS Tally
FROM 
    ranges a
ORDER BY Tally DESC
0 голосов
/ 17 сентября 2011

Как насчет этого?

SELECT TOP 1
       ranges.date_start,
       COUNT(data.page) AS Tally
  FROM (SELECT DISTINCT 
               date_page_requested AS date_start,
               DATEADD(HOUR,1,date_page_requested) AS date_end
          FROM @Table) ranges
  JOIN @Table data
    ON data.date_page_requested >= ranges.date_start
   AND data.date_page_requested < ranges.date_end
 GROUP BY ranges.date_start
 ORDER BY Tally DESC
0 голосов
/ 17 сентября 2011

Для PostgreSQL я бы сначала написал что-то вроде этого для «окна», выровненного по минутам. Для этого вам не нужны оконные функции OLAP.

select w.ts, 
       date_trunc('minute', w.ts) as hour_start, 
       date_trunc('minute', w.ts) + interval '1' hour as hour_end,
       (select count(*) 
        from weblog 
        where ts between date_trunc('minute', w.ts) and 
                        (date_trunc('minute', w.ts) + interval '1' hour) ) as num_pages
from weblog w
group by ts, hour_start, hour_end
order by num_pages desc

Oracle также имеет функцию trunc (), но я не уверен в формате. Я либо посмотрю его через минуту, либо уеду посмотреть бурлеск-шоу друга.

0 голосов
/ 17 сентября 2011

Это должно дать вам то, что вам нужно, первая строка должна иметь час с наибольшим количеством страниц.

select number_of_pages
      ,hour_requested
from (select to_char(date_page_requested,'dd/mm/yyyy hh') hour_requested
            ,count(*) number_of_pages
      from pages
      group by to_char(date_page_requested,'dd/mm/yyyy hh')) p
order by number_of_pages
...