From ddeb1a9f331de434a4d2f60a5e9ec8c39b5e64ec Mon Sep 17 00:00:00 2001 From: alexeychal Date: Thu, 4 Jun 2026 14:54:12 +0000 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20timeBasedReport.sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- timeBasedReport.sql | 120 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 timeBasedReport.sql diff --git a/timeBasedReport.sql b/timeBasedReport.sql new file mode 100644 index 0000000..db9cdbf --- /dev/null +++ b/timeBasedReport.sql @@ -0,0 +1,120 @@ +-- ============================================================================= +-- Отчет повременного учета работоспособности периферийного оборудования +-- Период: май 2026 +-- Исключены устройства, начинающиеся на IRZ +-- Тип оборудования берется из инвентаризации Zabbix (поле type) +-- Координаты: широта + долгота из полей location_lat и location_lon +-- ============================================================================= + +WITH +-- 1. Получаем все проверки ICMP за период +checks AS ( + SELECT + h.host AS "Устройство", + COALESCE(h.name, h.host) AS "Видимое имя", + -- Тип оборудования из инвентаризации (поле type), если пусто - берем hardware + COALESCE(hinv."name", 'не указан') AS "Тип оборудования", + -- Номер объекта ИТС РО (храним в поле notes инвентаризации) + COALESCE(hinv.notes, '') AS "Номер_объекта_ИТС_РО", + -- Координаты: объединяем широту и долготу через пробел + 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 "Координаты_расположения", + -- Время проверки с учетом часового пояса + 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 + -- Исключаем оборудование, начинающееся на IRZ (любой регистр) + --AND UPPER(h.host) NOT LIKE 'IRZ%' + -- Период: май 2026 года (измените под свои даты) + --and hinv.notes = 'ОБЪЕКТ № 9' + and CAST(nullif(regexp_replace(hinv.notes, 'ОБЪЕКТ №\s*', '', 'g'),'') as INTEGER) + in (44,77,43,54,27,48,12,49,65,9,60,35,38,1,51,41,53,84,8) + AND hx.clock >= EXTRACT(EPOCH FROM TIMESTAMP '2026-05-25 00:00:00') + AND hx.clock < EXTRACT(EPOCH FROM TIMESTAMP '2026-06-01 00:00:00') +), + +-- 2. Добавляем предыдущий статус для определения моментов смены +checks_with_prev AS ( + SELECT + *, + LAG("status") OVER (PARTITION BY "Устройство" ORDER BY "ts") AS "prev_status" + FROM checks +), + +-- 3. Определяем моменты смены статуса (начало нового интервала) +status_changes AS ( + SELECT + *, + CASE + WHEN "prev_status" IS NULL OR "status" != "prev_status" THEN 1 + ELSE 0 + END AS "is_start" + FROM checks_with_prev +), + +-- 4. Нумеруем интервалы для каждого устройства +intervals AS ( + SELECT + *, + SUM("is_start") OVER (PARTITION BY "Устройство" ORDER BY "ts") AS "interval_id" + FROM status_changes + WHERE "status" IS NOT NULL +), + +-- 5. Агрегируем каждый непрерывный интервал +grouped_intervals AS ( + SELECT + "Устройство", + "Видимое имя", + "Тип оборудования", + "Номер_объекта_ИТС_РО", + "Координаты_расположения", + MIN("ts") AS "time_start", + MAX("ts") AS "time_end", + MAX("status") AS "status" + FROM intervals + GROUP BY + "Устройство", + "Видимое имя", + "Тип оборудования", + "Номер_объекта_ИТС_РО", + "Координаты_расположения", + "interval_id" +) + +-- 6. Финальный вывод отчета +SELECT + ROW_NUMBER() OVER (ORDER BY "Устройство", "time_start") AS "№ п/п", + TO_CHAR(DATE("time_start"), 'DD.MM.YYYY') AS "Дата", + "Тип оборудования", + "Номер_объекта_ИТС_РО", + "Координаты_расположения", + TO_CHAR("time_start", 'HH24:MI:SS') AS "Время начала статуса", + TO_CHAR("time_end", 'HH24:MI:SS') AS "Время окончания статуса", + CASE + WHEN "status" = 1 THEN 'доступно' + ELSE 'недоступно' + END AS "Статус" +FROM grouped_intervals +ORDER BY "Номер_объекта_ИТС_РО"; \ No newline at end of file