diff --git a/balalaika.sql b/balalaika.sql deleted file mode 100644 index 43cb509..0000000 --- a/balalaika.sql +++ /dev/null @@ -1,407 +0,0 @@ --- ============================================================================= --- Отчет повременного учета работоспособности периферийного оборудования --- Период: май 2026 --- Исключены устройства, начинающиеся на IRZ --- Тип оборудования берется из инвентаризации Zabbix (поле type) --- Координаты: широта + долгота из полей location_lat и location_lon --- ============================================================================= - - -WITH --- 1. Получаем все проверки ICMP за период -checks AS ( - SELECT - h.host AS host_name, - COALESCE(h.name, h.host) AS visible_name, - -- Тип оборудования из инвентаризации (поле type), если пусто - берем hardware - COALESCE(hinv."name", 'не указан') AS equipment_type, - -- Номер объекта ИТС РО (храним в поле notes инвентаризации) - COALESCE(hinv.notes, '') AS object_number, - -- Координаты: объединяем широту и долготу через пробел - CASE - WHEN hinv.location_lat IS NOT NULL AND hinv.location_lon IS NOT NULL - AND hinv.location_lat != '' AND hinv.location_lon != '' - THEN hinv.location_lat || ' ' || hinv.location_lon - WHEN hinv.location_lat IS NOT NULL AND hinv.location_lat != '' - THEN hinv.location_lat - WHEN hinv.location_lon IS NOT NULL AND hinv.location_lon != '' - THEN hinv.location_lon - ELSE '' - END AS coordinates, - -- Время проверки с учетом часового пояса - TO_TIMESTAMP(hx.clock) AT TIME ZONE 'Europe/Moscow' AS ts, - -- Статус: 1 = доступно, 0 = недоступно - hx.value AS status - FROM hosts h - INNER JOIN items i - ON i.hostid = h.hostid - AND i.key_ = 'icmpping' - AND i.status = 0 - AND i.value_type = 3 -- unsigned numeric - INNER JOIN history_uint hx - ON hx.itemid = i.itemid - LEFT JOIN host_inventory hinv - ON hinv.hostid = h.hostid - WHERE - -- Только мониторимые хосты - h.status = 0 - and COALESCE(h.name, h.host) not like '%WIMAX' - -- Исключаем оборудование, начинающееся на IRZ (любой регистр) - -- AND UPPER(h.host) NOT LIKE 'IRZ%' - -- Период: май 2026 года (измените под свои даты) - and hinv.notes is not null and hinv.notes <> '' - --and hinv.notes = 'ОБЪЕКТ № 67' --and hinv.name like '%Маршрутизатор%' - and CAST(nullif(regexp_replace(hinv.notes, 'ОБЪЕКТ №\s*', '', 'g'),'') as INTEGER) - --between 1 and 85 - in (1,2,4,5,8,9,11,12,14,24,25,27,28,29,30,31,32,34,35,36,38,40,41,42,43,44,45,46,48,49,50,51,53,54,55,57,58,60,62,63,64,65,66,67,68,69,70,76,77,81,82,84,85) - --AND hx.clock >= EXTRACT(EPOCH FROM TIMESTAMP '2026-06-01 00:00:00') - --AND hx.clock < EXTRACT(EPOCH FROM TIMESTAMP '2026-06-05 00:00:00') - AND TO_TIMESTAMP(hx.clock) >= to_date(${start_dt}, 'yyyymmdd') - interval '1 day' - AND TO_TIMESTAMP(hx.clock) <= to_date(${end_dt}, 'yyyymmdd') + interval '1 day' -), -- 2. Добавляем предыдущий статус для определения моментов смены -checks_with_prev AS ( - SELECT - *, - LAG(status) OVER (PARTITION BY host_name ORDER BY ts) AS prev_status, - coalesce(lead(ts) OVER (PARTITION BY host_name ORDER BY ts), date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + interval '1 month') AS next_ts - FROM checks -), --3. Определяем моменты смены статуса (начало нового интервала) -status_changes AS ( - SELECT - host_name, - visible_name, - equipment_type, - object_number, - coordinates, - ts, - status, - prev_status, - case - when DATE(next_ts) > DATE(ts) then date_trunc('day', next_ts) + interval '00:00:00' - else next_ts - interval '1 sec' - end as next_ts, - case - when DATE(next_ts) > DATE(ts) then date_trunc('day', next_ts) + interval '00:00:00' - else next_ts - end as next_check_time, - CASE WHEN status != prev_status THEN 1 - ELSE 0 - END AS is_start - FROM checks_with_prev - union all - SELECT - host_name, - visible_name, - equipment_type, - object_number, - coordinates, - date_trunc('day', next_ts) + interval '00:00:00' as ts, - status, - prev_status, - next_ts - interval '1 sec' as next_ts, - next_ts as next_check_time, - 1 as is_start - FROM checks_with_prev - where DATE(next_ts) > DATE(ts) -), -- 4. Нумеруем интервалы для каждого устройства -intervals AS ( - SELECT - *, - SUM(is_start) OVER (PARTITION BY host_name ORDER BY ts) AS interval_id - FROM status_changes - WHERE status IS NOT null - and date_trunc('day', ts) >= to_date(${start_dt}, 'yyyymmdd') and date_trunc('day', ts) <= to_date(${end_dt}, 'yyyymmdd') -), -- 5. Агрегируем каждый непрерывный интервал -grouped_intervals AS ( - SELECT - host_name, - visible_name, - equipment_type, - object_number, - coordinates, - max(regexp_replace(object_number, 'ОБЪЕКТ №\s*', '', 'g'))::int as object_num, - MIN(ts) AS time_start, - MAX(next_ts) AS time_end, - MAX(next_check_time) AS time_end_all, - MAX(status) AS status - FROM intervals - GROUP BY - host_name, - visible_name, - equipment_type, - object_number, - coordinates, - interval_id -), -- 5_1. Определение маршрутизатора (заглушка) -router as -( - select - m.host_name, - m.visible_name, - m.equipment_type, - v.object_number, - v.coordinates, - v.object_num, - v.time_start, - v.time_end, - v.time_end_all, - v.status - from grouped_intervals v - join - ( - select host_name, visible_name, object_number, equipment_type, date_trunc('day', time_start) as time_start_dt, object_num - from grouped_intervals - where equipment_type like 'Маршрутизатор%' - group by 1,2,3,4,5,6 - ) m on m.object_num = v.object_num - where v.equipment_type like 'Видеокамера%' - and time_start_dt = date_trunc('day', v.time_start) -), union_zab as -( - select * - , case - when equipment_type like 'Метеостанция%' then '1' - when equipment_type like 'Видеокамера%' then '2' - when equipment_type like 'Маршрутизатор%' then '3' - when object_num = 38 and equipment_type like 'Детектор транспортных потоков CTfind DTM 1' then 'Детектор транспортных потоков №1' - when object_num = 38 and equipment_type like 'Детектор транспортных потоков CTfind DTM 2' then 'Детектор транспортных потоков №2' - else equipment_type - end as equipment_id - , DATE(time_start) AS date_check - , row_number() over(partition by DATE(time_start), object_num, equipment_type order by time_start desc) as rn - from - ( - select * from grouped_intervals where equipment_type not like 'Маршрутизатор%' - union all - select * from router - ) u -), sum_interval as -( - select - equipment_id, - object_num, - date_check, - case - when available_hours = '1 day' then '24:00:00'::interval - else available_hours::interval - end as available_hours - from - ( - SELECT - equipment_id, - object_num, - date_check, - sum(time_end_all - time_start) AS available_hours - FROM union_zab u - where status = 1 - GROUP BY equipment_id, object_num, date_check - ) s -), gant as -( - select DATE(date_check) as date_check, object_name, equipment_type, coordinates - , regexp_replace(object_name, 'ОБЪЕКТ №\s*', '', 'g')::int as object_num - , case - when equipment_type like 'Метеостанция%' then '1' - when equipment_type like 'Видеокамера%' then '2' - when equipment_type like 'Роутер%' then '3' - else equipment_type - end as equipment_id - , time_start as sum_hours - , coalesce(LPAD(FLOOR(time_start)::INT::TEXT, 2, '0') || ':' || - LPAD(FLOOR((time_start- FLOOR(time_start)::INT) * 60)::INT::TEXT, 2, '0') || ':' || - LPAD(ROUND(((time_start - FLOOR(time_start)::INT) * 60 - FLOOR((time_start- FLOOR(time_start)::INT) * 60)::INT) * 60)::INT::TEXT, 2, '0'), '00:00:00')::interval as aval - from - ( - select object_name, equipment_type, d01 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) as date_check from gantt_contractor - union all - select object_name, equipment_type, d02 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '1 day'from gantt_contractor - union all - select object_name, equipment_type, d03 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '2 day'from gantt_contractor - union all - select object_name, equipment_type, d04 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '3 day'from gantt_contractor - union all - select object_name, equipment_type, d05 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '4 day'from gantt_contractor - union all - select object_name, equipment_type, d06 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '5 day'from gantt_contractor - union all - select object_name, equipment_type, d07 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '6 day'from gantt_contractor - union all - select object_name, equipment_type, d08 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '7 day'from gantt_contractor - union all - select object_name, equipment_type, d09 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '8 day'from gantt_contractor - union all - select object_name, equipment_type, d10 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '9 day'from gantt_contractor - union all - select object_name, equipment_type, d11 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '10 day'from gantt_contractor - union all - select object_name, equipment_type, d12 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '11 day'from gantt_contractor - union all - select object_name, equipment_type, d13 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '12 day'from gantt_contractor - union all - select object_name, equipment_type, d14 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '13 day'from gantt_contractor - union all - select object_name, equipment_type, d15 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '14 day'from gantt_contractor - union all - select object_name, equipment_type, d16 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '15 day'from gantt_contractor - union all - select object_name, equipment_type, d17 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '16 day'from gantt_contractor - union all - select object_name, equipment_type, d18 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '17 day'from gantt_contractor - union all - select object_name, equipment_type, d19 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '18 day'from gantt_contractor - union all - select object_name, equipment_type, d20 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '19 day'from gantt_contractor - union all - select object_name, equipment_type, d21 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '20 day'from gantt_contractor - union all - select object_name, equipment_type, d22 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '21 day'from gantt_contractor - union all - select object_name, equipment_type, d23 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '22 day'from gantt_contractor - union all - select object_name, equipment_type, d24 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '23 day'from gantt_contractor - union all - select object_name, equipment_type, d25 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '24 day'from gantt_contractor - union all - select object_name, equipment_type, d26 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '25 day'from gantt_contractor - union all - select object_name, equipment_type, d27 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '26 day'from gantt_contractor - union all - select object_name, equipment_type, d28 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '27 day'from gantt_contractor - union all - select object_name, equipment_type, d29 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '28 day'from gantt_contractor - union all - select object_name, equipment_type, d30 as time_start, coordinates, date_trunc('month', to_date(${start_dt}, 'yyyymmdd')) + INTERVAL '29 day'from gantt_contractor - ) g - where date_check >= to_date(${start_dt}, 'yyyymmdd') and date_check <= to_date(${end_dt}, 'yyyymmdd') -), gant_interval as -( - select date_check, object_name, equipment_type, object_num, equipment_id, coordinates - , 1 as status, INTERVAL '00:00:00' as time_start_tm, INTERVAL '24:00:00' as time_end_tm - from gant - where sum_hours = 24 - union all - select date_check, object_name, equipment_type, object_num, equipment_id, coordinates - , 1 as status, INTERVAL '00:00:00' as time_start_tm, aval::interval as time_end_tm - from gant - where sum_hours > 0 and sum_hours < 24 - union all - select date_check, object_name, equipment_type, object_num, equipment_id, coordinates - , 0 as status, aval::interval + INTERVAL '1 second' as time_start_tm, INTERVAL '00:00:00' as time_end_tm - from gant - where sum_hours > 0 and sum_hours < 24 - union all - select date_check, object_name, equipment_type, object_num, equipment_id, coordinates - , 0 as status, INTERVAL '00:00:00' as time_start_tm, INTERVAL '24:00:00' as time_end_tm - from gant - where sum_hours = 0 - union all - select date_check, object_name, equipment_type, object_num, equipment_id, coordinates - , 0 as status, aval::interval, aval::interval - from gant - where sum_hours is null -), gener as -( - select g.*, i.available_hours, g.time_end_tm - i.available_hours as diff_tm - , case when g.time_end_tm > i.available_hours then 1 else 0 end as diff_fl - from gant_interval g - left join sum_interval i on g.object_num = i.object_num - and g.equipment_id = i.equipment_id - and g.date_check = i.date_check - where abs(extract('minute' from g.time_end_tm - i.available_hours)::int) > 5 - and g.status = 1 - union all - select g.*, i.available_hours, INTERVAL '00:00:00' as diff_tm, null as diff_fl - from gant_interval g - left join sum_interval i on g.object_num = i.object_num - and g.equipment_id = i.equipment_id - and g.date_check = i.date_check - where i.available_hours is null -), gener_gant_interval as -( - select gi.date_check, g.equipment_id, g.object_num, z.status - , case - when z.status = 1 and z.rn = 1 then z.time_start - DATE_trunc('day', z.time_start) - diff_tm - when z.status = 0 and z.rn = 2 then z.time_start - DATE_trunc('day', z.time_start) - when z.status = 0 and z.rn = 1 then z.time_start - DATE_trunc('day', z.time_start) - diff_tm - when z.status = 1 and z.rn = 2 then z.time_start - DATE_trunc('day', z.time_start) - else z.time_start - DATE_trunc('day', z.time_start) - end as time_start_tm - , case - when z.status = 1 and z.rn = 1 then z.time_end - DATE_trunc('day', z.time_end) - when z.status = 0 and z.rn = 2 then z.time_end - DATE_trunc('day', z.time_end) - diff_tm - when z.status = 0 and z.rn = 1 then z.time_end - DATE_trunc('day', z.time_end) - when z.status = 1 and z.rn = 2 then z.time_end - DATE_trunc('day', z.time_end) - diff_tm - else z.time_end - DATE_trunc('day', z.time_end) - end as time_end_tm - from gener g - join gant_interval gi on g.object_num = gi.object_num and g.equipment_id = gi.equipment_id and g.date_check = gi.date_check - join union_zab z on g.object_num = z.object_num and g.equipment_id = z.equipment_id and g.date_check = z.date_check - where g.diff_fl = 1 --в zabbix < - union - select gi.date_check, g.equipment_id, g.object_num, z.status - , case - when z.status = 1 and z.rn = 1 then z.time_start - DATE_trunc('day', z.time_start) + diff_tm - when z.status = 0 and z.rn = 2 then z.time_start - DATE_trunc('day', z.time_start) - when z.status = 0 and z.rn = 1 then z.time_start - DATE_trunc('day', z.time_start) + diff_tm - when z.status = 1 and z.rn = 2 then z.time_start - DATE_trunc('day', z.time_start) - else z.time_start - DATE_trunc('day', z.time_start) - end as time_start_tm - , case - when z.status = 1 and z.rn = 1 then z.time_end - DATE_trunc('day', z.time_end) - when z.status = 0 and z.rn = 2 then z.time_end - DATE_trunc('day', z.time_end) + diff_tm - when z.status = 0 and z.rn = 1 then z.time_end - DATE_trunc('day', z.time_end) - when z.status = 1 and z.rn = 2 then z.time_end - DATE_trunc('day', z.time_end) + diff_tm - else z.time_end - DATE_trunc('day', z.time_end) - end as time_end_tm - from gener g - join gant_interval gi on g.object_num = gi.object_num and g.equipment_id = gi.equipment_id and g.date_check = gi.date_check - join union_zab z on g.object_num = z.object_num and g.equipment_id = z.equipment_id and g.date_check = z.date_check - where g.diff_fl = 0 --в zabbix > -), main as -( - select g.date_check as date_check - , coalesce(u.object_num, g.object_num) as object_num - , coalesce(u.equipment_id, g.equipment_id) as equipment_id - , coalesce(u.equipment_type, g.equipment_type) as equipment_type - , coalesce(u.object_number, g.object_name) as object_name - , greatest(u.coordinates::varchar, g.coordinates::varchar) as coordinates - from gant g - left join union_zab u on u.object_num = g.object_num - and g.equipment_id = u.equipment_id - group by 1,2,3,4,5,6 -) --- 6. Финальный вывод отчета -SELECT - ROW_NUMBER() OVER (order by m.date_check, m.object_num nulls last, m.equipment_type, u.time_start) AS "№ п/п", - TO_CHAR(DATE(m.date_check), 'DD.MM.YYYY') AS "Дата", - m.equipment_type as "Тип оборудования", - m.object_name as "Номер_объекта_ИТС_РО", - m.coordinates as "Координаты_расположения", - TO_CHAR(u.time_start, 'HH24:MI:SS') AS "Время начала статуса", - TO_CHAR(u.time_end, 'HH24:MI:SS') as "Время окончания статуса", - CASE - WHEN u.status = 1 THEN 'доступно' - ELSE 'недоступно' - END AS "Статус" -FROM main m -join -( - select * - from - ( - select gi.date_check, gi.equipment_id, gi.object_num, gi.status, gi.time_start_tm as time_start, gi.time_end_tm as time_end - from gener g - join gant_interval gi on g.object_num = gi.object_num and g.equipment_id = gi.equipment_id and g.date_check = gi.date_check - where g.diff_fl is null - union all - select date_check, equipment_id, object_num, status, time_start_tm, time_end_tm - from gener_gant_interval - union all - select uz.date_check, uz.equipment_id, uz.object_num, uz.status, uz.time_start - DATE_trunc('day', uz.time_start), uz.time_end - DATE_trunc('day', uz.time_start) - from union_zab uz - left join gener_gant_interval ggi on uz.object_num = ggi.object_num and uz.equipment_id = ggi.equipment_id and uz.date_check = ggi.date_check - where ggi.date_check is null - ) r -) u on m.object_num = u.object_num and m.equipment_id = u.equipment_id and m.date_check = u.date_check -ORDER BY 1 -; \ No newline at end of file