Как найти один период часа с большинством точек данных?

Иногда это происходит, когда на вашем компьютере установлено несколько копий Python Этот блог очень полезен.

9
задан OverloadUT 3 February 2009 в 19:00
поделиться

10 ответов

Учитывая таблицу, заполненную каждой минутой в году, Вы интересуетесь Minutes и таблица Posts с a Time столбец:

select top 1 minutes.time, count (posts.time)
from Minutes
   left join posts on posts.time >= minutes.time AND posts.time < dateadd(hour, 1, Minutes.Time)
group by minutes.time
order by count (posts.time) desc

Для решения генерации мелкой таблицы можно использовать функцию как ufn_GenerateIntegers. Затем функция становится

select top 5 minutes.time, count (posts.time)
from (select dateadd(minute, IntValue, '2008-01-01') as Time from ufn_GenerateIntegers(525600)) Minutes
   left join posts on posts.time >= minutes.time AND posts.time < dateadd(hour, 1, Minutes.Time)
group by minutes.time
order by count(posts.time) desc

Я просто сделал тестовый прогон приблизительно с 5 000 случайных сообщений, и потребовалось 16 секунд на моей машине. Так, не тривиальный, но не смешной для случайного одноразового запроса. К счастью, это - точка данных, можно вычислить один день или даже один раз в месяц и кэш, если Вы хотите отобразить значение часто.

Смотрите на улучшение lassevk.

5
ответ дан 4 December 2019 в 13:05
поделиться

Рассматривайте метку времени каждого сообщения как запуск такого часа и считайте все другие сообщения, которые находятся в пределах в тот час, включая сообщение, которое запустило его. Отсортируйте получающиеся часы в порядке убывания по количеству сообщений в каждом из них.

Сделав это, Вы найдете самый верхний единственный "час", который имеет большинство сообщений в нем, но этот промежуток времени не мог бы быть точно один час длиной, это могло бы быть короче (но никогда дольше).

Для получения "более симпатичного" периода можно вычислить, какой длины это действительно, разделитесь на два и скорректируйте запуск периода назад той суммой и концом вперед, это будет "центрировать" сообщения в часе. Эта корректировка, как гарантируют, не будет включать любые новые сообщения, таким образом, количество будет все еще допустимо. Если сообщения достаточно близки, чтобы внезапно быть включенными в период после расширения его до одного часа то более ранняя точка имела бы "большинство сообщений" в ней вместо той, которую Вы выбрали.

Если это - вопрос о SQL, можно снова использовать SQL, который Josh отправил здесь, просто замените таблицу Minutes другой ссылкой на таблицу сообщений.


Другой метод, который можно использовать, должен использовать раздвижное окно.

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

Теперь, для каждого сообщения, добавьте его в конец списка. Затем для каждого сообщения от запуска списка, если то сообщение больше чем за один час до сообщения, Вы просто добавили, удалите его из списка.

После выполнения, что операция с 2 шагами для единственного нового сообщения в списке, проверьте, является ли количество сообщений в списке больше, чем предыдущий максимум, и если это, или сделайте копию списка или по крайней мере сохраните сообщение, которое Вы просто добавили.

После того, как Вы закончены, у Вас есть "копия списка" с большинством сообщений за час, или Вы получили сообщение, которое является концом 1-часового окна, которое содержит большинство сообщений.

Псевдокод:

initialize posts-window-list to empty list
for each post in sorted-posts-list:
    add post to end of posts-window-list
    for each other-post from start of posts-window-list:
        if other-post is more than one hour older than post, remove it
        otherwise, end this inner loop
    if number of posts in list is more than previous maximum:
        make copy of list, this is the new maximum
2
ответ дан 4 December 2019 в 13:05
поделиться

Это работало над небольшой тестовой БАЗОЙ ДАННЫХ SQL MS.

SELECT TOP 1 id, date_entered,
  (SELECT COUNT(*)
   FROM   dbo.notes AS n2
   WHERE n2.date_entered >= n.date_entered 
   AND n2.date_entered < Dateadd(hh, 1, n.date_entered)) AS num
FROM  dbo.notes n
ORDER BY num DESC

Это не очень эффективно, проверки на основе часа до каждого сообщения.

For MYSQL 

SELECT ID,f.Date, (SELECT COUNT(*)
FROM Forum AS f2
WHERE f2.Date >= f.Date AND f2.Date < Date_ADD(f.Date, INTERVAL 1 HOUR)) As num
FROM Forum AS f
ORDER BY num
LIMIT 0,1
2
ответ дан 4 December 2019 в 13:05
поделиться

Binning будет работать, если Вы захотите посмотреть с промежутками, такие как 10:00 - 11:00. Однако, если у Вас был внезапный шквал интереса с 10:30 - 11:30 затем, он будет разделен через два мусорных ведра и следовательно может быть скрыт меньшим числом хитов, которые, оказалось, соответствовали полностью в течение единственного часа часов.

Единственный способ избежать этой проблемы состоит в том, чтобы генерировать список, отсортированный по времени, и ступить через нее. Что-то вроде этого:

max = 0; maxTime = 0
for each $item in the list:
   push $item onto queue
   while head of queue is more than an hour before $item
      drop queue head.
   if queue.count > max then max = queue.count; maxTime = $item.time

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

4
ответ дан 4 December 2019 в 13:05
поделиться

Вот небольшая вариация на реализацию другого Josh's, это воздерживается от непосредственной таблицы и использует сам соединение на себе, ища любые сообщения в течение часа после того одного сообщения.

select top 1 posts.DateCreated, count (posts.datecreated),
min(minutes.DateCreated) as MinPostDate,
max(minutes.datecreated) as MaxPostDate
from posts Minutes   
left join posts on posts.datecreated >= minutes.DateCreated 
AND posts.datecreated < dateadd(hour, 1, Minutes.DateCreated)
group by posts.DateCreated
order by count(posts.datecreated) desc

Со взгляда производительности на таблицу только с 6 строками его метод, который использовал функцию для генерации intermiadte таблицы, занял 16 секунд по сравнению с этим, который был подвторым.

Я не положителен, если это было бы возможное использование этого для пропавших без вести допустимого периода времени, так как промежуток базируется прочь смещения каждого сообщения.

1
ответ дан 4 December 2019 в 13:05
поделиться

Если mysql:

select substr( timestamp, 1, 16 ) as hour, count(*) as count from forum_posts group by hour order by count desc limit 1;

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

0
ответ дан 4 December 2019 в 13:05
поделиться

Это приводит к O (n) запрос базы данных и O (n) самый большой поиск времени, для общей сложности O (2n) (который, конечно, является все еще O (n)):

Используйте количество отличная команда в SQL, который будет объекты 'мусорного ведра' для Вас в мелких инкрементах.

Таким образом, Вы выполнили запрос количества на этой таблице:

time
1
2      
4
3
3
2
4
1
3
2

И это возвратилось бы:

0 1
1 1
2 3
3 3
4 2

Путем подсчета каждого объекта.

Я подозреваю, что можно сделать то же самое с таблицей и мусорное ведро их к минуте, затем выполнить алгоритм на этом.

SELECT customer_name, COUNT(DISTINCT city) as "Distinct Cities"
FROM customers
GROUP BY customer_name;

Из этого учебного руководства на количестве: http://www.techonthenet.com/sql/count.php (около конца).

Вот похожая страница из руководства MySQL: http://dev.mysql.com/doc/refman/5.1/en/counting-rows.html

Таким образом, если у Вас есть таблица с timedate в нем (к минуте, позволяя binning происходить к минутам):

datetime (yyyymmddhhmm)
200901121435
200901121538
200901121435
200901121538
200901121435
200901121538
200901121538
200901121435
200901121435
200901121538
200901121435
200901121435

Затем SQL

SELECT datetime, COUNT(DISTINCT datetime) as "Date Time"
FROM post
GROUP BY datetime;

должен возвратиться

200901121435 7
200901121538 5

Необходимо будет все еще отправить, обрабатывают это, но тяжелая работа группировки и подсчета сделана и только приведет к только по 500k строкам в год (60 минут, 24 часа, 365 дней)

Обработка сообщения была бы:

Start at time T = first post time.
Set greatestTime = T
Sum all counts between T and T+one hour --> currentHourCount and greatestHourCount
While records exist past T+one hour
   Increment T by one minute.
   While the first element is prior to time T, subtract it
   while the last element is before time T+ one hour, add it
   If currentHourCount > greatestHourCount then
      greatestHourCount = currentHourCount
      greatestTime = T
end while

- Adam

1
ответ дан 4 December 2019 в 13:05
поделиться

Это сделает это.

ВЫБЕРИТЕ DateOfEvent HourBegin, DATEADD (гд, 1, DateOfEvent)), HourEnd, КОЛИЧЕСТВО (*) AS NumEventsPerHour ОТ tEvents AS tEvents AS B СОЕДИНЕНИЯ НА A.DateOfEvent> = B.DateOfEvents И DATEADD (гд, 1, A.DateOfEvent) <= B.DateOfEvent GROUP BY A.DateOfEvent

1
ответ дан 4 December 2019 в 13:05
поделиться

При использовании MySQL:

SELECT DATE(postDate), HOUR(postDate), COUNT(*) AS n
FROM posts
GROUP BY DATE(postDate), HOUR(postDate)
ORDER BY n DESC
LIMIT 1
0
ответ дан 4 December 2019 в 13:05
поделиться
SELECT  DATEPART(hour, PostDateTime) AS HourOfDay,
        COUNT(*) AS ForumPosts
FROM    Posts
GROUP BY DATEPART(hour, PostDateTime)
0
ответ дан 4 December 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: