MySQL: средний интервал между записями - PullRequest
21 голосов
/ 30 ноября 2010

Допустим, эта таблица:

id    date
----------------
1     2010-12-12
2     2010-12-13
3     2010-12-18
4     2010-12-22
5     2010-12-23

Как найти средние интервалы между этими датами, используя только запросы MySQL?

Например, расчет по этой таблице будет

  (
    ( 2010-12-13 - 2010-12-12 )
  + ( 2010-12-18 - 2010-12-13 )
  + ( 2010-12-22 - 2010-12-18 )
  + ( 2010-12-23 - 2010-12-22 )
  ) / 4
----------------------------------
= ( 1 DAY + 5 DAY + 4 DAY + 1 DAY ) / 4
= 2.75 DAY

Ответы [ 4 ]

39 голосов
/ 30 ноября 2010

Интуитивно понятно, что вы спрашиваете, должно быть эквивалентно интервалу между первой и последней датами, деленному на число дат минус 1.

Позвольте мне объяснить более подробно.Представьте, что даты - это точки на линии (+ - это даты, - - это отсутствие даты, первая дата - 12-е, и я изменил последнюю дату на 24 декабря для целей иллюстрации):

++----+---+-+

Теперь, что вы действительно хотите сделать, - это равномерно распределить даты между этими строками и определить, сколько времени проходит между каждой из них:

+--+--+--+--+

Чтобы сделать это, вы просто беретеколичество дней между последним и первым днями, в данном случае 24 - 12 = 12, и разделите его на количество интервалов, которые вы должны разнести, в данном случае 4: 12 / 4 = 3.

С помощьюMySQL запрос

SELECT DATEDIFF(MAX(dt), MIN(dt)) / (COUNT(dt) - 1) FROM a;

Это работает для этой таблицы (с вашими значениями она возвращает 2,75):

CREATE TABLE IF NOT EXISTS `a` (
  `dt` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO `a` (`dt`) VALUES
('2010-12-12'),
('2010-12-13'),
('2010-12-18'),
('2010-12-22'),
('2010-12-24');
2 голосов
/ 30 ноября 2010

Если идентификаторы равномерно увеличиваются без пробелов, присоедините таблицу к себе по id + 1:

SELECT d.id, d.date, n.date, datediff(d.date, n.date)
FROM dates d
JOIN dates n ON(n.id = d.id + 1)

Затем GROUP BY и среднее значение по необходимости.

Если идентификаторы не являются одинаковыми, сначала выполните внутренний запрос, чтобы назначить упорядоченные идентификаторы.

Полагаю, вам также нужно добавить подзапрос, чтобы получить общее количество строк.

Альтернативно

Создать статистическую функцию, которая отслеживает предыдущую дату, а также промежуточную сумму и счет. Вам все равно придется выбирать из подзапроса, чтобы принудительно упорядочить по дате (на самом деле, я не уверен, гарантировано ли это в MySQL).

Если подумать, это гораздо лучший способ сделать это.

И даже проще

Просто отметив, что решение Вегарда намного лучше.

1 голос
/ 30 ноября 2010

Следующий запрос возвращает правильный результат

SELECT AVG(
        DATEDIFF(i.date, (SELECT MAX(date) 
                          FROM intervals WHERE date < i.date)
                 )
           )
FROM intervals i

но он выполняет зависимый подзапрос, который может быть действительно неэффективным без индекса и с большим числом строк.

0 голосов
/ 30 ноября 2010

Вам нужно самостоятельно объединиться и получить различия, используя функцию DATEDIFF, и получить среднее значение.

...