powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Группировка по времени на не фиксированные промежутки
8 сообщений из 8, страница 1 из 1
Группировка по времени на не фиксированные промежутки
    #38395791
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Уважаемые гуру, помогите пожалуйста со следующей задачей.
Имеем таблицу с неким логом падений устройств, стоящих на мониторинге (даже скорее не логом, а с активными событиями, т.к. поле device уникально):

event_id device time1Switch42013-09-01 00:01:002Switch12013-09-01 00:02:303Switch102013-09-01 00:02:404Switch512013-09-01 03:05:005Switch492013-09-02 13:00:006Switch282013-09-02 13:01:007Switch92013-09-02 13:02:00

Устройства как правило "падают" либо по 1-му, либо группой (в случае если "падает" узловое оборудование), но в случае падаения группой - записи заноситься в эту систему не с одинаковым TIMESTAMP'ом, а с разницей примерно +/-3 минуты . Задача стоит в том чтобы проанализировать лог и разделить события по группам(общим авариям) в зависимости от времени, но так чтобы перед первым и последним падением не прошло более 3-х минут (т.е. имеем не фиксированные промежутки времени).

Я представляю себе это выделением дополнительной колонки в которой будем группировать устройства по времени падения +/-3 минуты, т.е

event_id device time group1Switch42013-09-01 00:01:00 12Switch12013-09-01 00:02:30 13Switch102013-09-01 00:02:40 14Switch512013-09-01 03:05:00 25Switch492013-09-02 13:00:00 36Switch282013-09-02 13:01:00 37Switch92013-09-02 13:02:00 3

Первое что приходит на ум это использование оконных функций, но к сожалению в выражении автор[ RANGE | ROWS ] BETWEEN frame_start AND frame_end нельзя указывать что-то отличное от авторUNBOUNDED PRECEDING
value PRECEDING
CURRENT ROW
value FOLLOWING
UNBOUNDED FOLLOWING где value авторvalue must be an integer expression not containing any variables, aggregate functions, or window functions Да и подумав пришёл к выводу, что даже возможность указывать INTERVAL это не помогла бы.

Прошу помощи у Вас, возможно кто-то сталкивался с подобным.
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38395855
Фотография Misha Tyurin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SkyFire,

1)

сначала бегите по окну на всю выборку упорядоченную по временем и смотрите разницу с лагом, и если эта разница для строки больше интервала (например, 2 минуты), то помечаем это временем строки.

2)после первого прохода делаем второй, все пустые руонамберы запоняем лоагом.
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38395893
Фотография Misha Tyurin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Misha Tyurin,

недописал.

---

1)

сначала бегите по окну на всю выборку упорядоченную по временем и смотрите разницу с лагом, и если эта разница для строки больше интервала (например, 2 минуты), то помечаем это временем строки.

2)

после первого прохода делаем второй, все пустые отметки заполняем "максимальной"

3) и третий

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
with

  data( id, t ) as 
  (
    values
    
      ( 1000, 1 ),
      ( 1001, 2 ),
      ( 1002, 3 ),

      ( 1000, 7 ),
      ( 1004, 8 )
      
  ),
  
  x( id, t, xx ) as
  (
    select *, case coalesce((t - lag(t) over (order by t)), 2) >= 2 when true then t end
    from
      data
   ),
   xx(id, t, t2) as
   (
     select id, t, max(xx) over (order by t) from x
   )

select id, t, ( ( min(t) over w )::text || '-' || ( max(t) over w )::text ) as xperiod
from xx
window
  w as ( partition by t2 )


Код: plaintext
1.
2.
3.
4.
5.
1000;1;"1-3"
1001;2;"1-3"
1002;3;"1-3"
1000;7;"7-8"
1004;8;"7-8"
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38395908
Фотография Misha Tyurin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Misha Tyurin,

http://www.depesz.com/2010/09/12/how-to-group-messages-into-chats/

всё придумано до нас
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38396081
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Misha Tyurin,
то что нужно! Огромнейшее спасибо!
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38396185
SkyFire
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если кому ещё пригодится - на СО предложили тоже интересные решения.
http://stackoverflow.com/questions/18782363/group-by-floating-date-range
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38669262
khuawei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Грез было не поделиться элегантным решением... Итак 3 дня искал решение, но все, что нашел - было достаточно громоздко. В итоге решил поискать округление по датам и нашел функцию, которая округляла не совсем так как надо ( http://wiki.postgresql.org/wiki/Round_time) Вот здесь функция огругления по интервалу. Немного доработал ф-ю и получил то что надо
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
CREATE OR REPLACE FUNCTION public.date_round (
  base_date timestamp,
  round_interval interval
)
RETURNS TIMESTAMP WITHOUT TIME ZONE AS
$body$
DECLARE
   res TIMESTAMP;
BEGIN   
	res := TIMESTAMP 'epoch' + (EXTRACT(epoch FROM $1)::INTEGER + EXTRACT(epoch FROM $2)::INTEGER / 2)
                / EXTRACT(epoch FROM $2)::INTEGER * EXTRACT(epoch FROM $2)::INTEGER * INTERVAL '1 second';            
    IF (base_date > res ) THEN
    	res := res + $2;
    END IF;
    RETURN res;
END;
$body$
LANGUAGE 'plpgsql'
STABLE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;



А далее просто группируем по результатам функции:

Код: sql
1.
SELECT t.* FROM (SELECT p.oper_date, date_round(p.oper_date, '5 minutes') as grp FROM test p) t GROUP BY t.grp



Соответственно меняем интервал округления.
...
Рейтинг: 0 / 0
Группировка по времени на не фиксированные промежутки
    #38670705
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khuawei,


Ток начал переходить на эту субд, поэтому интересно
Код: sql
1.
2.
res := TIMESTAMP 'epoch' + (EXTRACT(epoch FROM $1)::INTEGER + EXTRACT(epoch FROM $2)::INTEGER / 2)
                / EXTRACT(epoch FROM $2)::INTEGER * EXTRACT(epoch FROM $2)::INTEGER * INTERVAL '1 second'; 





Код: sql
1.
2.
3.
4.
5.
res := TIMESTAMP 'epoch' + 

(EXTRACT(epoch FROM $1)::INTEGER + 
 EXTRACT(epoch FROM $2)::INTEGER / 2)   /     EXTRACT(epoch FROM $2)::INTEGER 
                                                               *     EXTRACT(epoch FROM $2)::INTEGER * INTERVAL '1 second'; 


тут случаем ничего нельзя сократить?

или это скрытая реклама автопреобразования типов?

а главное, не подходит для данной задачи.

понаходить логи за интервалы времени, и разбить шкалу времени на интервалы, и на основании этого разбиения групировать - это не одно и тоже!!!
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Группировка по времени на не фиксированные промежутки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]